https://github.com/akkartik/mu/blob/master/apps/mu.subx
    1 # The Mu computer's level-2 language, also called Mu.
    2 # http://akkartik.name/post/mu-2019-2
    3 #
    4 # To run:
    5 #   $ ./translate_subx init.linux [0-9]*.subx apps/mu.subx
    6 #   $ ./a.elf < prog.mu > prog.elf
    7 
    8 # == Goals
    9 # 1. Be memory safe. It should be impossible to corrupt the heap, or to create
   10 # a bad pointer. (Requires strong type safety.)
   11 # 2. Do as little as possible to achieve goal 1. The translator should be
   12 # implementable in machine code.
   13 #   - minimize impedance mismatch between source language and SubX target
   14 #     (e.g. programmer manages registers manually)
   15 #   - checks over syntax
   16 #     (e.g. programmer's register allocation is checked)
   17 #   - runtime checks to avoid complex static analysis
   18 #     (e.g. array indexing always checks bounds)
   19 
   20 # == Language description
   21 # A program is a sequence of function and type definitions.
   22 #
   23 # Function example:
   24 #   fn foo n: int -> _/eax: int {
   25 #     ...
   26 #   }
   27 #
   28 # Functions consist of a name, optional inputs, optional outputs and a block.
   29 #
   30 # Function inputs and outputs are variables. All variables have a type and
   31 # storage specifier. They can be placed either in memory (on the stack) or in
   32 # one of 6 named registers.
   33 #   eax ecx edx ebx esi edi
   34 # Variables in registers must be primitive 32-bit types.
   35 # Variables not explicitly placed in a register are on the stack.
   36 #
   37 # Function inputs are always passed in memory (on the stack), while outputs
   38 # are always returned in registers. Outputs can't be named; they use the
   39 # dummy value '_'.
   40 #
   41 # Blocks mostly consist of statements.
   42 #
   43 # Statements mostly consist of a name, optional inputs and optional outputs.
   44 #
   45 # Statement inputs are variables or literals. Variables need to specify type
   46 # (and storage) the first time they're mentioned but not later.
   47 #
   48 # Statement outputs, like function outputs, must be variables in registers.
   49 #
   50 # Statement names must be either primitives or user-defined functions.
   51 #
   52 # Primitives can write to any register.
   53 # User-defined functions only write to hard-coded registers. Outputs of each
   54 # call must have the same registers as in the function definition.
   55 #
   56 # There are some other statement types:
   57 #   - blocks. Multiple statements surrounded by '{...}' and optionally
   58 #     prefixed with a label name and ':'
   59 #       - {
   60 #           ...
   61 #         }
   62 #       - foo: {
   63 #           ...
   64 #         }
   65 #
   66 #   - variable definitions on the stack. E.g.:
   67 #       - var foo: int
   68 #       - var bar: (array int 3)
   69 #     There's no initializer; variables are automatically initialized.
   70 #     The type of a local variable is either word-length (4 bytes) or starts with 'ref'.
   71 #
   72 #   - variables definitions in a register. E.g.:
   73 #       - var foo/eax: int <- add bar 1
   74 #     The initializer is mandatory and must be a valid instruction that writes
   75 #     a single output to the right register. In practice registers will
   76 #     usually be either initialized by primitives or copied from eax.
   77 #       - var eax: int <- foo bar quux
   78 #         var floo/ecx: int <- copy eax
   79 #
   80 # Still todo:
   81 #   global variables
   82 #   union types
   83 #
   84 # Formal types:
   85 #   A program is a linked list of functions
   86 #   A function contains:
   87 #     name: (handle array byte)
   88 #     inouts: linked list of vars  <-- 'inouts' is more precise than 'inputs'
   89 #       data: (handle var)
   90 #       next: (handle list)
   91 #     outputs: linked list of vars
   92 #       data: (handle var)
   93 #       next: (handle list)
   94 #     body: (handle block)
   95 #   A var-type contains:
   96 #     name: (handle array byte)
   97 #     type: (handle type-tree)
   98 #
   99 #   A statement can be:
  100 #     tag 0: a block
  101 #     tag 1: a simple statement (stmt1)
  102 #     tag 2: a variable defined on the stack
  103 #     tag 3: a variable defined in a register
  104 #
  105 #   A block contains:
  106 #     tag: 0
  107 #     statements: (handle list stmt)
  108 #     name: (handle array byte) -- starting with '$'
  109 #
  110 #   A regular statement contains:
  111 #     tag: 1
  112 #     operation: (handle array byte)
  113 #     inouts: (handle list operand)
  114 #     outputs: (handle list var)
  115 #
  116 #   A variable defined on the stack contains:
  117 #     tag: 2
  118 #     name: (handle array byte)
  119 #     type: (handle type-tree)
  120 #
  121 #   A variable defined in a register contains:
  122 #     tag: 3
  123 #     name: (handle array byte)
  124 #     type: (handle type-tree)
  125 #     reg: (handle array byte)
  126 
  127 # == Translation: managing the stack
  128 # Now that we know what the language looks like in the large, let's think
  129 # about how translation happens from the bottom up. One crucial piece of the
  130 # puzzle is how Mu will clean up variables defined on the stack for you.
  131 #
  132 # Assume that we maintain a 'functions' list while parsing source code. And a
  133 # 'primitives' list is a global constant. Both these contain enough information
  134 # to perform type-checking on function calls or primitive statements, respectively.
  135 #
  136 # Defining variables pushes them on a stack with the current block depth and
  137 # enough information about their location (stack offset or register).
  138 # Starting a block increments the current block id.
  139 # Each statement now has enough information to emit code for it.
  140 # Ending a block is where the magic happens:
  141 #   pop all variables at the current block depth
  142 #   emit code to restore all register variables introduced at the current depth
  143 #   emit code to clean up all stack variables at the current depth (just increment esp)
  144 #   decrement the current block depth
  145 #
  146 # Formal types:
  147 #   live-vars: stack of vars
  148 #   var:
  149 #     name: (handle array byte)
  150 #     type: (handle type-tree)
  151 #     block: int
  152 #     stack-offset: int  (added to ebp)
  153 #     register: (handle array byte)
  154 #       either usual register names
  155 #       or '*' to indicate any register
  156 #   At most one of stack-offset or register-index must be non-zero.
  157 #   A register of '*' designates a variable _template_. Only legal in formal
  158 #   parameters for primitives.
  159 
  160 # == Translating a single function call
  161 # This one's easy. Assuming we've already checked things, we just drop the
  162 # outputs (which use hard-coded registers) and emit inputs in a standard format.
  163 #
  164 # out1, out2, out3, ... <- name inout1, inout2, inout3, ...
  165 # =>
  166 # (name inout1 inout2 inout3)
  167 #
  168 # Formal types:
  169 #   functions: linked list of info
  170 #     name: (handle array byte)
  171 #     inouts: linked list of vars
  172 #     outputs: linked list of vars
  173 #     body: block (linked list of statements)
  174 
  175 # == Translating a single primitive instruction
  176 # A second crucial piece of the puzzle is how Mu converts fairly regular
  177 # primitives with their uniform syntax to SubX instructions with their gnarly
  178 # x86 details.
  179 #
  180 # Mu instructions have inputs and outputs. Primitives can have up to 2 of
  181 # them.
  182 # SubX instructions have rm32 and r32 operands.
  183 # The translation between them covers almost all the possibilities.
  184 #   Instructions with 1 inout may turn into ones with 1 rm32
  185 #     (e.g. incrementing a var on the stack)
  186 #   Instructions with 1 output may turn into ones with 1 rm32
  187 #     (e.g. incrementing a var in a register)
  188 #   1 inout and 1 output may turn into 1 rm32 and 1 r32
  189 #     (e.g. adding a var to a reg)
  190 #   2 inouts may turn into 1 rm32 and 1 r32
  191 #     (e.g. adding a reg to a var)
  192 #   1 inout and 1 literal may turn into 1 rm32 and 1 imm32
  193 #     (e.g. adding a constant to a var)
  194 #   1 output and 1 literal may turn into 1 rm32 and 1 imm32
  195 #     (e.g. adding a constant to a reg)
  196 #   2 outputs to hardcoded registers and 1 inout may turn into 1 rm32
  197 #     (special-case: divide edx:eax by a var or reg)
  198 # Observations:
  199 #   We always emit rm32. It may be the first inout or the first output.
  200 #   We may emit r32 or imm32 or neither.
  201 #   When we emit r32 it may come from first inout or second inout or first output.
  202 #
  203 # Accordingly, the formal data structure for a primitive looks like this:
  204 #   primitives: linked list of info
  205 #     name: (handle array byte)
  206 #     mu-inouts: linked list of vars to check
  207 #     mu-outputs: linked list of vars to check; at most a singleton
  208 #     subx-name: (handle array byte)
  209 #     subx-rm32: enum arg-location
  210 #     subx-r32: enum arg-location
  211 #     subx-imm32: enum arg-location
  212 #     subx-imm8: enum arg-location
  213 #     subx-disp32: enum arg-location
  214 #     subx-xm32: enum arg-location
  215 #     subx-x32: enum arg-location
  216 #   arg-location: enum
  217 #     0 means none
  218 #     1 means first inout
  219 #     2 means second inout
  220 #     3 means first output
  221 
  222 # == Translating a block
  223 # Emit block name if necessary
  224 # Emit '{'
  225 # When you encounter a statement, emit it as above
  226 # When you encounter a variable declaration
  227 #   emit any code needed for it (bzeros)
  228 #   push it on the var stack
  229 #   update register dict if necessary
  230 # When you encounter '}'
  231 #   While popping variables off the var stack until block id changes
  232 #     Emit code needed to clean up the stack
  233 #       either increment esp
  234 #       or pop into appropriate register
  235 
  236 # The rest is straightforward.
  237 
  238 == data
  239 
  240 Program:
  241 _Program-functions:  # (handle function)
  242   0/imm32
  243 _Program-functions->payload:
  244   0/imm32
  245 _Program-types:  # (handle typeinfo)
  246   0/imm32
  247 _Program-types->payload:
  248   0/imm32
  249 _Program-signatures:  # (handle function)
  250   0/imm32
  251 _Program-signatures->payload:
  252   0/imm32
  253 
  254 # Some constants for simulating the data structures described above.
  255 # Many constants here come with a type in a comment.
  256 #
  257 # Sometimes the type is of the value at that offset for the given type. For
  258 # example, if you start at a function record and move forward Function-inouts
  259 # bytes, you'll find a (handle list var).
  260 #
  261 # At other times, the type is of the constant itself. For example, the type of
  262 # the constant Function-size is (addr int). To get the size of a function,
  263 # look in *Function-size.
  264 
  265 Function-name:  # (handle array byte)
  266   0/imm32
  267 Function-inouts:  # (handle list var)
  268   8/imm32
  269 Function-outputs:  # (handle list var)
  270   0x10/imm32
  271 Function-body:  # (handle block)
  272   0x18/imm32
  273 Function-next:  # (handle function)
  274   0x20/imm32
  275 Function-size:  # (addr int)
  276   0x28/imm32/40
  277 
  278 Primitive-name:  # (handle array byte)
  279   0/imm32
  280 Primitive-inouts:  # (handle list var)
  281   8/imm32
  282 Primitive-outputs:  # (handle list var)
  283   0x10/imm32
  284 Primitive-subx-name:  # (handle array byte)
  285   0x18/imm32
  286 Primitive-subx-rm32:  # enum arg-location
  287   0x20/imm32
  288 Primitive-subx-r32:  # enum arg-location
  289   0x24/imm32
  290 Primitive-subx-imm32:  # enum arg-location
  291   0x28/imm32
  292 Primitive-subx-imm8:  # enum arg-location  -- only for bit shifts
  293   0x2c/imm32
  294 Primitive-subx-disp32:  # enum arg-location  -- only for branches
  295   0x30/imm32
  296 Primitive-subx-xm32:  # enum arg-location
  297   0x34/imm32
  298 Primitive-subx-x32:  # enum arg-location
  299   0x38/imm32
  300 Primitive-next:  # (handle function)
  301   0x3c/imm32
  302 Primitive-size:  # (addr int)
  303   0x44/imm32/68
  304 
  305 Stmt-tag:  # int
  306   0/imm32
  307 
  308 Block-stmts:  # (handle list stmt)
  309   4/imm32
  310 Block-var:  # (handle var)
  311   0xc/imm32
  312 
  313 Stmt1-operation:  # (handle array byte)
  314   4/imm32
  315 Stmt1-inouts:  # (handle stmt-var)
  316   0xc/imm32
  317 Stmt1-outputs:  # (handle stmt-var)
  318   0x14/imm32
  319 
  320 Vardef-var:  # (handle var)
  321   4/imm32
  322 
  323 Regvardef-operation:  # (handle array byte)
  324   4/imm32
  325 Regvardef-inouts:  # (handle stmt-var)
  326   0xc/imm32
  327 Regvardef-outputs:  # (handle stmt-var)  # will have exactly one element
  328   0x14/imm32
  329 
  330 Stmt-size:  # (addr int)
  331   0x1c/imm32
  332 
  333 Var-name:  # (handle array byte)
  334   0/imm32
  335 Var-type:  # (handle type-tree)
  336   8/imm32
  337 Var-block-depth:  # int -- not available until code-generation time
  338   0x10/imm32
  339 Var-offset:  # int -- not available until code-generation time
  340   0x14/imm32
  341 Var-register:  # (handle array byte) -- name of a register
  342   0x18/imm32
  343 Var-size:  # (addr int)
  344   0x20/imm32
  345 
  346 List-value:  # (handle _)
  347   0/imm32
  348 List-next:  # (handle list _)
  349   8/imm32
  350 List-size:  # (addr int)
  351   0x10/imm32
  352 
  353 # A stmt-var is like a list of vars with call-site specific metadata
  354 Stmt-var-value:  # (handle var)
  355   0/imm32
  356 Stmt-var-next:  # (handle stmt-var)
  357   8/imm32
  358 Stmt-var-is-deref:  # boolean
  359   0x10/imm32
  360 Stmt-var-size:  # (addr int)
  361   0x14/imm32
  362 
  363 # A live-var is a var augmented with information needed for tracking live
  364 # variables.
  365 Live-var-value:  # (handle var)
  366   0/imm32
  367 Live-var-register-spilled:  # boolean; only used if value is in a register, and only during code-gen
  368   8/imm32
  369 Live-var-size:  # (addr int)
  370   0xc/imm32
  371 
  372 # Types are expressed as trees (s-expressions) of type-ids (ints).
  373 
  374 Type-tree-is-atom:  # boolean
  375   0/imm32
  376 # if is-atom?
  377 Type-tree-value:  # type-id
  378   4/imm32
  379 Type-tree-value-size:  # int (for static data structure sizes)
  380   8/imm32
  381 Type-tree-parameter-name:  # (handle array byte) for type parameters
  382   8/imm32
  383 # unless is-atom?
  384 Type-tree-left:  # (addr type-tree)
  385   4/imm32
  386 Type-tree-right:  # (addr type-tree)
  387   0xc/imm32
  388 #
  389 Type-tree-size:  # (addr int)
  390   0x14/imm32
  391 
  392 # Types
  393 
  394 # TODO: Turn this data structure into valid Mu, with (fake) handles rather than addrs.
  395 Type-id:  # (stream (addr array byte))
  396   0/imm32/write  # initialized later from Primitive-type-ids
  397   0/imm32/read
  398   0x100/imm32/size
  399   # data
  400   0/imm32  # 0 reserved for literals; value is just the name
  401            # Not to be used directly, so we don't include a name here.
  402   "int"/imm32  # 1
  403   "addr"/imm32  # 2
  404   "array"/imm32  # 3
  405   "handle"/imm32  # 4
  406   "boolean"/imm32  # 5
  407   0/imm32  # 6 reserved for constants; they're like literals, but value is an int in Var-offset
  408            # Not to be used directly, so we don't include a name here.
  409   "offset"/imm32  # 7: (offset T) is guaranteed to be a 32-bit multiple of size-of(T)
  410   # 0x20
  411   "byte"/imm32  # 8
  412   0/imm32  # 9 reserved for array-capacity; value is in Type-tree-size.
  413            # Not to be used directly, so we don't include a name here.
  414   0/imm32  # 10 reserved for type parameters; value is (address array byte) in Type-tree-value2.
  415            # Not to be used directly, so we don't include a name here.
  416   "stream"/imm32  # 11
  417   "slice"/imm32  # 12
  418   "code-point"/imm32  # 13; smallest scannable unit from a text stream
  419   "grapheme"/imm32  # 14; smallest printable unit; will eventually be composed of multiple code-points, but currently corresponds 1:1
  420                     # only 4-byte graphemes in utf-8 are currently supported;
  421                     # unclear how we should deal with larger clusters.
  422   "float"/imm32     # 15
  423   # 0x40
  424   0/imm32  # 16 reserved for literal strings; value is just the name
  425            # Not to be used directly, so we don't include a name here.
  426            # TODO: move this up next to literal ints
  427   # Keep Primitive-type-ids in sync if you add types here.
  428           0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  429   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  430   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  431   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  432   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  433   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
  434 
  435 Primitive-type-ids:  # (addr int)
  436   0x44
  437 
  438 # == Type definitions
  439 # Program->types contains some typeinfo for each type definition.
  440 # Types contain vars with types, but can't specify registers.
  441 Typeinfo-id:  # type-id
  442   0/imm32
  443 Typeinfo-fields:  # (handle table (handle array byte) (handle typeinfo-entry))
  444   4/imm32
  445 # Total size must be >= 0
  446 # During parsing it may take on two additional values:
  447 #   -2: not yet initialized
  448 #   -1: in process of being computed
  449 # See populate-mu-type-sizes for details.
  450 Typeinfo-total-size-in-bytes:  # int
  451   0xc/imm32
  452 Typeinfo-next:  # (handle typeinfo)
  453   0x10/imm32
  454 Typeinfo-size:  # (addr int)
  455   0x18/imm32
  456 
  457 # Each entry in the typeinfo->fields table has a pointer to a string and a
  458 # pointer to a typeinfo-entry.
  459 Typeinfo-fields-row-size:  # (addr int)
  460   0x10/imm32
  461 
  462 # typeinfo-entry objects have information about a field in a single record type
  463 #
  464 # each field of a type is represented using two var's:
  465 #   1. the input var: expected type of the field; convenient for creating using parse-var-with-type
  466 #   2. the output var: a constant containing the byte offset; convenient for code-generation
  467 # computing the output happens after parsing; in the meantime we preserve the
  468 # order of fields in the 'index' field.
  469 Typeinfo-entry-input-var:  # (handle var)
  470   0/imm32
  471 Typeinfo-entry-index:  # int
  472   8/imm32
  473 Typeinfo-entry-output-var:  # (handle var)
  474   0xc/imm32
  475 Typeinfo-entry-size:  # (addr int)
  476   0x14/imm32
  477 
  478 == code
  479 
  480 Entry:
  481     # . prologue
  482     89/<- %ebp 4/r32/esp
  483     (new-segment *Heap-size Heap)
  484     # if (argv[1] == "test') run-tests()
  485     {
  486       # if (argc <= 1) break
  487       81 7/subop/compare *ebp 1/imm32
  488       7e/jump-if-<= break/disp8
  489       # if (argv[1] != "test") break
  490       (kernel-string-equal? *(ebp+8) "test")  # => eax
  491       3d/compare-eax-and 0/imm32/false
  492       74/jump-if-= break/disp8
  493       #
  494       (run-tests)
  495       # syscall(exit, *Num-test-failures)
  496       8b/-> *Num-test-failures 3/r32/ebx
  497       eb/jump $mu-main:end/disp8
  498     }
  499     # otherwise convert Stdin
  500     (convert-mu Stdin Stdout Stderr 0)
  501     (flush Stdout)
  502     # syscall(exit, 0)
  503     bb/copy-to-ebx 0/imm32
  504 $mu-main:end:
  505     e8/call syscall_exit/disp32
  506 
  507 convert-mu:  # in: (addr buffered-file), out: (addr buffered-file), err: (addr buffered-file), ed: (addr exit-descriptor)
  508     # . prologue
  509     55/push-ebp
  510     89/<- %ebp 4/r32/esp
  511     # . save registers
  512     50/push-eax
  513     # initialize global data structures
  514     c7 0/subop/copy *Next-block-index 1/imm32
  515     8b/-> *Primitive-type-ids 0/r32/eax
  516     89/<- *Type-id 0/r32/eax  # stream-write
  517     c7 0/subop/copy *_Program-functions 0/imm32
  518     c7 0/subop/copy *_Program-functions->payload 0/imm32
  519     c7 0/subop/copy *_Program-types 0/imm32
  520     c7 0/subop/copy *_Program-types->payload 0/imm32
  521     c7 0/subop/copy *_Program-signatures 0/imm32
  522     c7 0/subop/copy *_Program-signatures->payload 0/imm32
  523     #
  524     (parse-mu *(ebp+8) *(ebp+0x10) *(ebp+0x14))
  525     (populate-mu-type-sizes *(ebp+0x10) *(ebp+0x14))
  526 #?     (dump-typeinfos "=== typeinfos\n")
  527     (check-mu-types *(ebp+0x10) *(ebp+0x14))
  528     (emit-subx *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
  529 $convert-mu:end:
  530     # . restore registers
  531     58/pop-to-eax
  532     # . epilogue
  533     89/<- %esp 5/r32/ebp
  534     5d/pop-to-ebp
  535     c3/return
  536 
  537 test-convert-empty-input:
  538     # empty input => empty output
  539     # . prologue
  540     55/push-ebp
  541     89/<- %ebp 4/r32/esp
  542     # setup
  543     (clear-stream _test-input-stream)
  544     (clear-stream $_test-input-buffered-file->buffer)
  545     (clear-stream _test-output-stream)
  546     (clear-stream $_test-output-buffered-file->buffer)
  547     #
  548     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  549     (flush _test-output-buffered-file)
  550     (check-stream-equal _test-output-stream "" "F - test-convert-empty-input")
  551     # . epilogue
  552     89/<- %esp 5/r32/ebp
  553     5d/pop-to-ebp
  554     c3/return
  555 
  556 test-convert-function-skeleton:
  557     # . prologue
  558     55/push-ebp
  559     89/<- %ebp 4/r32/esp
  560     # setup
  561     (clear-stream _test-input-stream)
  562     (clear-stream $_test-input-buffered-file->buffer)
  563     (clear-stream _test-output-stream)
  564     (clear-stream $_test-output-buffered-file->buffer)
  565     #
  566     (write _test-input-stream "fn foo {\n")
  567     (write _test-input-stream "}\n")
  568     # convert
  569     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  570     (flush _test-output-buffered-file)
  571 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
  577     # check output
  578     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-skeleton/0")
  579     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-skeleton/1")
  580     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-skeleton/2")
  581     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-skeleton/3")
  582     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-skeleton/4")
  583     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-skeleton/5")
  584     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-skeleton/6")
  585     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-skeleton/7")
  586     # . epilogue
  587     89/<- %esp 5/r32/ebp
  588     5d/pop-to-ebp
  589     c3/return
  590 
  591 test-convert-multiple-function-skeletons:
  592     # . prologue
  593     55/push-ebp
  594     89/<- %ebp 4/r32/esp
  595     # setup
  596     (clear-stream _test-input-stream)
  597     (clear-stream $_test-input-buffered-file->buffer)
  598     (clear-stream _test-output-stream)
  599     (clear-stream $_test-output-buffered-file->buffer)
  600     #
  601     (write _test-input-stream "fn foo {\n")
  602     (write _test-input-stream "}\n")
  603     (write _test-input-stream "fn bar {\n")
  604     (write _test-input-stream "}\n")
  605     # convert
  606     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  607     (flush _test-output-buffered-file)
  608 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
  614     # check first function
  615     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-multiple-function-skeletons/0")
  616     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-multiple-function-skeletons/1")
  617     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-multiple-function-skeletons/2")
  618     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-multiple-function-skeletons/3")
  619     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-multiple-function-skeletons/4")
  620     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-multiple-function-skeletons/5")
  621     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-multiple-function-skeletons/6")
  622     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-multiple-function-skeletons/7")
  623     # check second function
  624     (check-next-stream-line-equal _test-output-stream "bar:"                    "F - test-convert-multiple-function-skeletons/10")
  625     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-multiple-function-skeletons/11")
  626     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-multiple-function-skeletons/12")
  627     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-multiple-function-skeletons/13")
  628     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-multiple-function-skeletons/14")
  629     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-multiple-function-skeletons/15")
  630     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-multiple-function-skeletons/16")
  631     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-multiple-function-skeletons/17")
  632     # . epilogue
  633     89/<- %esp 5/r32/ebp
  634     5d/pop-to-ebp
  635     c3/return
  636 
  637 test-convert-function-with-arg:
  638     # . prologue
  639     55/push-ebp
  640     89/<- %ebp 4/r32/esp
  641     # setup
  642     (clear-stream _test-input-stream)
  643     (clear-stream $_test-input-buffered-file->buffer)
  644     (clear-stream _test-output-stream)
  645     (clear-stream $_test-output-buffered-file->buffer)
  646     #
  647     (write _test-input-stream "fn foo n: int {\n")
  648     (write _test-input-stream "}\n")
  649     # convert
  650     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
  651     (flush _test-output-buffered-file)
  652 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
  658     # check output
  659     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-arg/0")
  660     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-arg/1")
  661     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-arg/2")
  662     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-arg/3")
  663     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-arg/4")
  664     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-arg/5")
  665     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-arg/6")
  666     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-arg/7")
  667     # . epilogue
  668     89/<- %esp 5/r32/ebp
  669     5d/pop-to-ebp
  670     c3/return
  671 
  672 test-function-with-redefined-name:
  673     # . prologue
  674     55/push-ebp
  675     89/<- %ebp 4/r32/esp
  676     # setup
  677     (clear-stream _test-input-stream)
  678     (clear-stream $_test-input-buffered-file->buffer)
  679     (clear-stream _test-output-stream)
  680     (clear-stream $_test-output-buffered-file->buffer)
  681     (clear-stream _test-error-stream)
  682     (clear-stream $_test-error-buffered-file->buffer)
  683     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  684     68/push 0/imm32
  685     68/push 0/imm32
  686     89/<- %edx 4/r32/esp
  687     (tailor-exit-descriptor %edx 0x10)
  688     #
  689     (write _test-input-stream "fn foo {\n")
  690     (write _test-input-stream "}\n")
  691     (write _test-input-stream "fn foo {\n")
  692     (write _test-input-stream "}\n")
  693     # convert
  694     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  695     # registers except esp clobbered at this point
  696     # restore ed
  697     89/<- %edx 4/r32/esp
  698     (flush _test-output-buffered-file)
  699     (flush _test-error-buffered-file)
  700 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
  706     # check output
  707     (check-stream-equal _test-output-stream  ""  "F - test-function-with-redefined-name: output should be empty")
  708     (check-next-stream-line-equal _test-error-stream  "fn foo defined more than once"  "F - test-function-with-redefined-name: error message")
  709     # check that stop(1) was called
  710     (check-ints-equal *(edx+4) 2 "F - test-function-with-redefined-name: exit status")
  711     # don't restore from ebp
  712     81 0/subop/add %esp 8/imm32
  713     # . epilogue
  714     5d/pop-to-ebp
  715     c3/return
  716 
  717 test-function-with-redefined-name-2:
  718     # . prologue
  719     55/push-ebp
  720     89/<- %ebp 4/r32/esp
  721     # setup
  722     (clear-stream _test-input-stream)
  723     (clear-stream $_test-input-buffered-file->buffer)
  724     (clear-stream _test-output-stream)
  725     (clear-stream $_test-output-buffered-file->buffer)
  726     (clear-stream _test-error-stream)
  727     (clear-stream $_test-error-buffered-file->buffer)
  728     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  729     68/push 0/imm32
  730     68/push 0/imm32
  731     89/<- %edx 4/r32/esp
  732     (tailor-exit-descriptor %edx 0x10)
  733     #
  734     (write _test-input-stream "fn foo {\n")
  735     (write _test-input-stream "}\n")
  736     (write _test-input-stream "sig foo\n")
  737     # convert
  738     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  739     # registers except esp clobbered at this point
  740     # restore ed
  741     89/<- %edx 4/r32/esp
  742     (flush _test-output-buffered-file)
  743     (flush _test-error-buffered-file)
  744 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
  750     # check output
  751     (check-stream-equal _test-output-stream  ""  "F - test-function-with-redefined-name-2: output should be empty")
  752     (check-next-stream-line-equal _test-error-stream  "fn foo defined more than once"  "F - test-function-with-redefined-name-2: error message")
  753     # check that stop(1) was called
  754     (check-ints-equal *(edx+4) 2 "F - test-function-with-redefined-name-2: exit status")
  755     # don't restore from ebp
  756     81 0/subop/add %esp 8/imm32
  757     # . epilogue
  758     5d/pop-to-ebp
  759     c3/return
  760 
  761 test-function-with-redefined-name-3:
  762     # . prologue
  763     55/push-ebp
  764     89/<- %ebp 4/r32/esp
  765     # setup
  766     (clear-stream _test-input-stream)
  767     (clear-stream $_test-input-buffered-file->buffer)
  768     (clear-stream _test-output-stream)
  769     (clear-stream $_test-output-buffered-file->buffer)
  770     (clear-stream _test-error-stream)
  771     (clear-stream $_test-error-buffered-file->buffer)
  772     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  773     68/push 0/imm32
  774     68/push 0/imm32
  775     89/<- %edx 4/r32/esp
  776     (tailor-exit-descriptor %edx 0x10)
  777     #
  778     (write _test-input-stream "sig foo\n")
  779     (write _test-input-stream "fn foo {\n")
  780     (write _test-input-stream "}\n")
  781     # convert
  782     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  783     # registers except esp clobbered at this point
  784     # restore ed
  785     89/<- %edx 4/r32/esp
  786     (flush _test-output-buffered-file)
  787     (flush _test-error-buffered-file)
  788 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
  794     # check output
  795     (check-stream-equal _test-output-stream  ""  "F - test-function-with-redefined-name-3: output should be empty")
  796     (check-next-stream-line-equal _test-error-stream  "fn foo defined more than once"  "F - test-function-with-redefined-name-3: error message")
  797     # check that stop(1) was called
  798     (check-ints-equal *(edx+4) 2 "F - test-function-with-redefined-name-3: exit status")
  799     # don't restore from ebp
  800     81 0/subop/add %esp 8/imm32
  801     # . epilogue
  802     5d/pop-to-ebp
  803     c3/return
  804 
  805 test-function-with-inout-in-register:
  806     # . prologue
  807     55/push-ebp
  808     89/<- %ebp 4/r32/esp
  809     # setup
  810     (clear-stream _test-input-stream)
  811     (clear-stream $_test-input-buffered-file->buffer)
  812     (clear-stream _test-output-stream)
  813     (clear-stream $_test-output-buffered-file->buffer)
  814     (clear-stream _test-error-stream)
  815     (clear-stream $_test-error-buffered-file->buffer)
  816     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  817     68/push 0/imm32
  818     68/push 0/imm32
  819     89/<- %edx 4/r32/esp
  820     (tailor-exit-descriptor %edx 0x10)
  821     #
  822     (write _test-input-stream "fn foo x/eax: int {\n")
  823     (write _test-input-stream "}\n")
  824     # convert
  825     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  826     # registers except esp clobbered at this point
  827     # restore ed
  828     89/<- %edx 4/r32/esp
  829     (flush _test-output-buffered-file)
  830     (flush _test-error-buffered-file)
  831 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
  837     # check output
  838     (check-stream-equal _test-output-stream  ""  "F - test-function-with-inout-in-register: output should be empty")
  839     (check-next-stream-line-equal _test-error-stream  "fn foo: function inout 'x' cannot be in a register"  "F - test-function-with-inout-in-register: error message")
  840     # check that stop(1) was called
  841     (check-ints-equal *(edx+4) 2 "F - test-function-with-inout-in-register: exit status")
  842     # don't restore from ebp
  843     81 0/subop/add %esp 8/imm32
  844     # . epilogue
  845     5d/pop-to-ebp
  846     c3/return
  847 
  848 test-function-with-addr-output:
  849     # . prologue
  850     55/push-ebp
  851     89/<- %ebp 4/r32/esp
  852     # setup
  853     (clear-stream _test-input-stream)
  854     (clear-stream $_test-input-buffered-file->buffer)
  855     (clear-stream _test-output-stream)
  856     (clear-stream $_test-output-buffered-file->buffer)
  857     (clear-stream _test-error-stream)
  858     (clear-stream $_test-error-buffered-file->buffer)
  859     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  860     68/push 0/imm32
  861     68/push 0/imm32
  862     89/<- %edx 4/r32/esp
  863     (tailor-exit-descriptor %edx 0x10)
  864     #
  865     (write _test-input-stream "fn foo -> _/eax: (addr int) {\n")
  866     (write _test-input-stream "}\n")
  867     # convert
  868     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  869     # registers except esp clobbered at this point
  870     # restore ed
  871     89/<- %edx 4/r32/esp
  872     (flush _test-output-buffered-file)
  873     (flush _test-error-buffered-file)
  874 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
  880     # check output
  881     (check-stream-equal _test-output-stream  ""  "F - test-function-with-addr-output: output should be empty")
  882     (check-next-stream-line-equal _test-error-stream  "fn foo: output cannot have an addr type; that could allow unsafe addresses to escape the function"  "F - test-function-with-addr-output: error message")
  883     # check that stop(1) was called
  884     (check-ints-equal *(edx+4) 2 "F - test-function-with-addr-output: exit status")
  885     # don't restore from ebp
  886     81 0/subop/add %esp 8/imm32
  887     # . epilogue
  888     5d/pop-to-ebp
  889     c3/return
  890 
  891 test-function-with-addr-inout:
  892     # . prologue
  893     55/push-ebp
  894     89/<- %ebp 4/r32/esp
  895     # setup
  896     (clear-stream _test-input-stream)
  897     (clear-stream $_test-input-buffered-file->buffer)
  898     (clear-stream _test-output-stream)
  899     (clear-stream $_test-output-buffered-file->buffer)
  900     (clear-stream _test-error-stream)
  901     (clear-stream $_test-error-buffered-file->buffer)
  902     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  903     68/push 0/imm32
  904     68/push 0/imm32
  905     89/<- %edx 4/r32/esp
  906     (tailor-exit-descriptor %edx 0x10)
  907     #
  908     (write _test-input-stream "fn foo a: (addr addr int) {\n")
  909     (write _test-input-stream "}\n")
  910     # convert
  911     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  912     # registers except esp clobbered at this point
  913     # restore ed
  914     89/<- %edx 4/r32/esp
  915     (flush _test-output-buffered-file)
  916     (flush _test-error-buffered-file)
  917 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
  923     # check output
  924     (check-stream-equal _test-output-stream  ""  "F - test-function-with-addr-inout: output should be empty")
  925     (check-next-stream-line-equal _test-error-stream  "fn foo: inout 'a' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function"  "F - test-function-with-addr-inout: error message")
  926     # check that stop(1) was called
  927     (check-ints-equal *(edx+4) 2 "F - test-function-with-addr-inout: exit status")
  928     # don't restore from ebp
  929     81 0/subop/add %esp 8/imm32
  930     # . epilogue
  931     5d/pop-to-ebp
  932     c3/return
  933 
  934 test-function-with-addr-inout-2:
  935     # . prologue
  936     55/push-ebp
  937     89/<- %ebp 4/r32/esp
  938     # setup
  939     (clear-stream _test-input-stream)
  940     (clear-stream $_test-input-buffered-file->buffer)
  941     (clear-stream _test-output-stream)
  942     (clear-stream $_test-output-buffered-file->buffer)
  943     (clear-stream _test-error-stream)
  944     (clear-stream $_test-error-buffered-file->buffer)
  945     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  946     68/push 0/imm32
  947     68/push 0/imm32
  948     89/<- %edx 4/r32/esp
  949     (tailor-exit-descriptor %edx 0x10)
  950     #
  951     (write _test-input-stream "fn foo a: (addr array addr int) {\n")
  952     (write _test-input-stream "}\n")
  953     # convert
  954     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  955     # registers except esp clobbered at this point
  956     # restore ed
  957     89/<- %edx 4/r32/esp
  958     (flush _test-output-buffered-file)
  959     (flush _test-error-buffered-file)
  960 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
  966     # check output
  967     (check-stream-equal _test-output-stream  ""  "F - test-function-with-addr-inout-2: output should be empty")
  968     (check-next-stream-line-equal _test-error-stream  "fn foo: inout 'a' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function"  "F - test-function-with-addr-inout-2: error message")
  969     # check that stop(1) was called
  970     (check-ints-equal *(edx+4) 2 "F - test-function-with-addr-inout-2: exit status")
  971     # don't restore from ebp
  972     81 0/subop/add %esp 8/imm32
  973     # . epilogue
  974     5d/pop-to-ebp
  975     c3/return
  976 
  977 test-function-with-addr-inout-3:
  978     # . prologue
  979     55/push-ebp
  980     89/<- %ebp 4/r32/esp
  981     # setup
  982     (clear-stream _test-input-stream)
  983     (clear-stream $_test-input-buffered-file->buffer)
  984     (clear-stream _test-output-stream)
  985     (clear-stream $_test-output-buffered-file->buffer)
  986     (clear-stream _test-error-stream)
  987     (clear-stream $_test-error-buffered-file->buffer)
  988     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
  989     68/push 0/imm32
  990     68/push 0/imm32
  991     89/<- %edx 4/r32/esp
  992     (tailor-exit-descriptor %edx 0x10)
  993     #
  994     (write _test-input-stream "fn foo a: (addr array (addr int) 3) {\n")
  995     (write _test-input-stream "}\n")
  996     # convert
  997     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
  998     # registers except esp clobbered at this point
  999     # restore ed
 1000     89/<- %edx 4/r32/esp
 1001     (flush _test-output-buffered-file)
 1002     (flush _test-error-buffered-file)
 1003 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1009     # check output
 1010     (check-stream-equal _test-output-stream  ""  "F - test-function-with-addr-inout-3: output should be empty")
 1011     (check-next-stream-line-equal _test-error-stream  "fn foo: inout 'a' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function"  "F - test-function-with-addr-inout-3: error message")
 1012     # check that stop(1) was called
 1013     (check-ints-equal *(edx+4) 2 "F - test-function-with-addr-inout-3: exit status")
 1014     # don't restore from ebp
 1015     81 0/subop/add %esp 8/imm32
 1016     # . epilogue
 1017     5d/pop-to-ebp
 1018     c3/return
 1019 
 1020 test-function-with-addr-inout-4:
 1021     # . prologue
 1022     55/push-ebp
 1023     89/<- %ebp 4/r32/esp
 1024     # setup
 1025     (clear-stream _test-input-stream)
 1026     (clear-stream $_test-input-buffered-file->buffer)
 1027     (clear-stream _test-output-stream)
 1028     (clear-stream $_test-output-buffered-file->buffer)
 1029     (clear-stream _test-error-stream)
 1030     (clear-stream $_test-error-buffered-file->buffer)
 1031     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1032     68/push 0/imm32
 1033     68/push 0/imm32
 1034     89/<- %edx 4/r32/esp
 1035     (tailor-exit-descriptor %edx 0x10)
 1036     #
 1037     (write _test-input-stream "fn foo a: (array (addr int) 3) {\n")
 1038     (write _test-input-stream "}\n")
 1039     # convert
 1040     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1041     # registers except esp clobbered at this point
 1042     # restore ed
 1043     89/<- %edx 4/r32/esp
 1044     (flush _test-output-buffered-file)
 1045     (flush _test-error-buffered-file)
 1046 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1052     # check output
 1053     (check-stream-equal _test-output-stream  ""  "F - test-function-with-addr-inout-4: output should be empty")
 1054     (check-next-stream-line-equal _test-error-stream  "fn foo: inout 'a' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function"  "F - test-function-with-addr-inout-4: error message")
 1055     # check that stop(1) was called
 1056     (check-ints-equal *(edx+4) 2 "F - test-function-with-addr-inout-4: exit status")
 1057     # don't restore from ebp
 1058     81 0/subop/add %esp 8/imm32
 1059     # . epilogue
 1060     5d/pop-to-ebp
 1061     c3/return
 1062 
 1063 # 'main' is an exception
 1064 test-function-main-with-addr-inout:
 1065     # . prologue
 1066     55/push-ebp
 1067     89/<- %ebp 4/r32/esp
 1068     # setup
 1069     (clear-stream _test-input-stream)
 1070     (clear-stream $_test-input-buffered-file->buffer)
 1071     (clear-stream _test-output-stream)
 1072     (clear-stream $_test-output-buffered-file->buffer)
 1073     #
 1074     (write _test-input-stream "fn main a: (addr addr int) {\n")
 1075     (write _test-input-stream "}\n")
 1076     # convert
 1077     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1078     (flush _test-output-buffered-file)
 1079     # no errors
 1080     # . epilogue
 1081     89/<- %esp 5/r32/ebp
 1082     5d/pop-to-ebp
 1083     c3/return
 1084 
 1085 # 'lookup' is an exception, but only in signatures
 1086 test-signature-lookup-with-addr-inout:
 1087     # . prologue
 1088     55/push-ebp
 1089     89/<- %ebp 4/r32/esp
 1090     # setup
 1091     (clear-stream _test-input-stream)
 1092     (clear-stream $_test-input-buffered-file->buffer)
 1093     (clear-stream _test-output-stream)
 1094     (clear-stream $_test-output-buffered-file->buffer)
 1095     #
 1096     (write _test-input-stream "sig lookup h: (handle _T) -> _/eax: (addr _T)\n")
 1097     # convert
 1098     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1099     (flush _test-output-buffered-file)
 1100     # no errors
 1101     # . epilogue
 1102     89/<- %esp 5/r32/ebp
 1103     5d/pop-to-ebp
 1104     c3/return
 1105 
 1106 test-convert-function-with-arg-and-body:
 1107     # . prologue
 1108     55/push-ebp
 1109     89/<- %ebp 4/r32/esp
 1110     # setup
 1111     (clear-stream _test-input-stream)
 1112     (clear-stream $_test-input-buffered-file->buffer)
 1113     (clear-stream _test-output-stream)
 1114     (clear-stream $_test-output-buffered-file->buffer)
 1115     #
 1116     (write _test-input-stream "fn foo n: int {\n")
 1117     (write _test-input-stream "  increment n\n")
 1118     (write _test-input-stream "}\n")
 1119     # convert
 1120     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1121     (flush _test-output-buffered-file)
 1122 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1128     # check output
 1129     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-arg-and-body/0")
 1130     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-arg-and-body/1")
 1131     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-arg-and-body/2")
 1132     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-arg-and-body/3")
 1133     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-arg-and-body/4")
 1134     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-arg-and-body/5")
 1135     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-arg-and-body/6")
 1136     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-arg-and-body/7")
 1137     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-arg-and-body/8")
 1138     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-arg-and-body/9")
 1139     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-arg-and-body/10")
 1140     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-arg-and-body/11")
 1141     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-arg-and-body/12")
 1142     # . epilogue
 1143     89/<- %esp 5/r32/ebp
 1144     5d/pop-to-ebp
 1145     c3/return
 1146 
 1147 test-convert-function-distinguishes-args:
 1148     # . prologue
 1149     55/push-ebp
 1150     89/<- %ebp 4/r32/esp
 1151     # setup
 1152     (clear-stream _test-input-stream)
 1153     (clear-stream $_test-input-buffered-file->buffer)
 1154     (clear-stream _test-output-stream)
 1155     (clear-stream $_test-output-buffered-file->buffer)
 1156     #
 1157     (write _test-input-stream "fn foo a: int, b: int {\n")
 1158     (write _test-input-stream "  increment b\n")
 1159     (write _test-input-stream "}\n")
 1160     # convert
 1161     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1162     (flush _test-output-buffered-file)
 1163 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1169     # check output
 1170     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-distinguishes-args/0")
 1171     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-distinguishes-args/1")
 1172     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-distinguishes-args/2")
 1173     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-distinguishes-args/3")
 1174     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-distinguishes-args/4")
 1175     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-distinguishes-args/5")
 1176     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *(ebp+0x0000000c)"  "F - test-convert-function-distinguishes-args/6")
 1177     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-distinguishes-args/7")
 1178     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-distinguishes-args/8")
 1179     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-distinguishes-args/9")
 1180     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-distinguishes-args/10")
 1181     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-distinguishes-args/11")
 1182     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-distinguishes-args/12")
 1183     # . epilogue
 1184     89/<- %esp 5/r32/ebp
 1185     5d/pop-to-ebp
 1186     c3/return
 1187 
 1188 test-convert-function-with-return-literal:
 1189     # . prologue
 1190     55/push-ebp
 1191     89/<- %ebp 4/r32/esp
 1192     # setup
 1193     (clear-stream _test-input-stream)
 1194     (clear-stream $_test-input-buffered-file->buffer)
 1195     (clear-stream _test-output-stream)
 1196     (clear-stream $_test-output-buffered-file->buffer)
 1197     #
 1198     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1199     (write _test-input-stream "  return 0\n")
 1200     (write _test-input-stream "}\n")
 1201     # convert
 1202     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1203     (flush _test-output-buffered-file)
 1204 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1210     # check output
 1211     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-literal/0")
 1212     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-literal/1")
 1213     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-literal/2")
 1214     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-literal/3")
 1215     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-literal/4")
 1216     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-literal/5")
 1217     (check-next-stream-line-equal _test-output-stream "    c7 0/subop/copy %eax 0/imm32"  "F - test-convert-function-with-return-literal/6")
 1218     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-literal/7")
 1219     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-literal/8")
 1220     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-literal/9")
 1221     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-literal/10")
 1222     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-literal/11")
 1223     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-literal/12")
 1224     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-literal/13")
 1225     # . epilogue
 1226     89/<- %esp 5/r32/ebp
 1227     5d/pop-to-ebp
 1228     c3/return
 1229 
 1230 test-convert-function-with-return:
 1231     # . prologue
 1232     55/push-ebp
 1233     89/<- %ebp 4/r32/esp
 1234     # setup
 1235     (clear-stream _test-input-stream)
 1236     (clear-stream $_test-input-buffered-file->buffer)
 1237     (clear-stream _test-output-stream)
 1238     (clear-stream $_test-output-buffered-file->buffer)
 1239     #
 1240     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1241     (write _test-input-stream "  var y: int\n")
 1242     (write _test-input-stream "  return y\n")
 1243     (write _test-input-stream "}\n")
 1244     # convert
 1245     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1246     (flush _test-output-buffered-file)
 1247 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1253     # check output
 1254     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return/0")
 1255     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return/1")
 1256     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return/2")
 1257     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return/3")
 1258     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return/4")
 1259     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return/5")
 1260     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-return/6")  # y
 1261     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0xfffffffc) 0x00000000/r32" "F - test-convert-function-with-return/7")
 1262     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-return/8")
 1263     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return/9")
 1264     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return/10")
 1265     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return/11")
 1266     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return/12")
 1267     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return/13")
 1268     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return/14")
 1269     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return/15")
 1270     # . epilogue
 1271     89/<- %esp 5/r32/ebp
 1272     5d/pop-to-ebp
 1273     c3/return
 1274 
 1275 test-convert-function-with-return-register:
 1276     # . prologue
 1277     55/push-ebp
 1278     89/<- %ebp 4/r32/esp
 1279     # setup
 1280     (clear-stream _test-input-stream)
 1281     (clear-stream $_test-input-buffered-file->buffer)
 1282     (clear-stream _test-output-stream)
 1283     (clear-stream $_test-output-buffered-file->buffer)
 1284     #
 1285     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1286     (write _test-input-stream "  var y/eax: int <- copy 3\n")
 1287     (write _test-input-stream "  return y\n")
 1288     (write _test-input-stream "}\n")
 1289     # convert
 1290     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1291     (flush _test-output-buffered-file)
 1292 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1298     # check output
 1299     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-register/0")
 1300     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-register/1")
 1301     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-register/2")
 1302     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-register/3")
 1303     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-register/4")
 1304     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-register/5")
 1305     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-with-return-register/6")
 1306     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 3/imm32"  "F - test-convert-function-with-return-register/7")
 1307     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32" "F - test-convert-function-with-return-register/8")
 1308     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-with-return-register/9")
 1309     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-register/10")
 1310     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-register/11")
 1311     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-register/12")
 1312     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-register/13")
 1313     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-register/14")
 1314     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-register/15")
 1315     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-register/16")
 1316     # . epilogue
 1317     89/<- %esp 5/r32/ebp
 1318     5d/pop-to-ebp
 1319     c3/return
 1320 
 1321 test-function-with-output-without-register:
 1322     # . prologue
 1323     55/push-ebp
 1324     89/<- %ebp 4/r32/esp
 1325     # setup
 1326     (clear-stream _test-input-stream)
 1327     (clear-stream $_test-input-buffered-file->buffer)
 1328     (clear-stream _test-output-stream)
 1329     (clear-stream $_test-output-buffered-file->buffer)
 1330     (clear-stream _test-error-stream)
 1331     (clear-stream $_test-error-buffered-file->buffer)
 1332     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1333     68/push 0/imm32
 1334     68/push 0/imm32
 1335     89/<- %edx 4/r32/esp
 1336     (tailor-exit-descriptor %edx 0x10)
 1337     #
 1338     (write _test-input-stream "fn foo -> _: int {\n")
 1339     (write _test-input-stream "}\n")
 1340     # convert
 1341     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1342     # registers except esp clobbered at this point
 1343     # restore ed
 1344     89/<- %edx 4/r32/esp
 1345     (flush _test-output-buffered-file)
 1346     (flush _test-error-buffered-file)
 1347 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1353     # check output
 1354     (check-stream-equal _test-output-stream  ""  "F - test-function-with-output-without-register: output should be empty")
 1355     (check-next-stream-line-equal _test-error-stream  "fn foo: function output '_' must be in a register, in instruction 'fn foo -> _: int {"  "F - test-function-with-output-without-register: error message")
 1356     # check that stop(1) was called
 1357     (check-ints-equal *(edx+4) 2 "F - test-function-with-output-without-register: exit status")
 1358     # don't restore from ebp
 1359     81 0/subop/add %esp 8/imm32
 1360     # . epilogue
 1361     5d/pop-to-ebp
 1362     c3/return
 1363 
 1364 test-function-with-outputs-in-conflicting-registers:
 1365     # . prologue
 1366     55/push-ebp
 1367     89/<- %ebp 4/r32/esp
 1368     # setup
 1369     (clear-stream _test-input-stream)
 1370     (clear-stream $_test-input-buffered-file->buffer)
 1371     (clear-stream _test-output-stream)
 1372     (clear-stream $_test-output-buffered-file->buffer)
 1373     (clear-stream _test-error-stream)
 1374     (clear-stream $_test-error-buffered-file->buffer)
 1375     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1376     68/push 0/imm32
 1377     68/push 0/imm32
 1378     89/<- %edx 4/r32/esp
 1379     (tailor-exit-descriptor %edx 0x10)
 1380     #
 1381     (write _test-input-stream "fn foo -> _/eax: int, _/eax: int {\n")
 1382     (write _test-input-stream "}\n")
 1383     # convert
 1384     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1385     # registers except esp clobbered at this point
 1386     # restore ed
 1387     89/<- %edx 4/r32/esp
 1388     (flush _test-output-buffered-file)
 1389     (flush _test-error-buffered-file)
 1390 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1396     # check output
 1397     (check-stream-equal _test-output-stream  ""  "F - test-function-with-outputs-in-conflicting-registers: output should be empty")
 1398     (check-next-stream-line-equal _test-error-stream  "fn foo: outputs must be in unique registers"  "F - test-function-with-outputs-in-conflicting-registers: error message")
 1399     # check that stop(1) was called
 1400     (check-ints-equal *(edx+4) 2 "F - test-function-with-outputs-in-conflicting-registers: exit status")
 1401     # don't restore from ebp
 1402     81 0/subop/add %esp 8/imm32
 1403     # . epilogue
 1404     5d/pop-to-ebp
 1405     c3/return
 1406 
 1407 test-function-with-named-output:
 1408     # . prologue
 1409     55/push-ebp
 1410     89/<- %ebp 4/r32/esp
 1411     # setup
 1412     (clear-stream _test-input-stream)
 1413     (clear-stream $_test-input-buffered-file->buffer)
 1414     (clear-stream _test-output-stream)
 1415     (clear-stream $_test-output-buffered-file->buffer)
 1416     (clear-stream _test-error-stream)
 1417     (clear-stream $_test-error-buffered-file->buffer)
 1418     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1419     68/push 0/imm32
 1420     68/push 0/imm32
 1421     89/<- %edx 4/r32/esp
 1422     (tailor-exit-descriptor %edx 0x10)
 1423     #
 1424     (write _test-input-stream "fn foo -> x/eax: int {\n")
 1425     (write _test-input-stream "  return 0\n")
 1426     (write _test-input-stream "}\n")
 1427     # convert
 1428     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1429     # registers except esp clobbered at this point
 1430     # restore ed
 1431     89/<- %edx 4/r32/esp
 1432     (flush _test-output-buffered-file)
 1433     (flush _test-error-buffered-file)
 1434 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1440     # check output
 1441     (check-stream-equal _test-output-stream  ""  "F - test-function-with-named-output: output should be empty")
 1442     (check-next-stream-line-equal _test-error-stream  "fn foo: function outputs cannot be named; rename 'x' in the header to '_'"  "F - test-function-with-named-output: error message")
 1443     # check that stop(1) was called
 1444     (check-ints-equal *(edx+4) 2 "F - test-function-with-named-output: exit status")
 1445     # don't restore from ebp
 1446     81 0/subop/add %esp 8/imm32
 1447     # . epilogue
 1448     5d/pop-to-ebp
 1449     c3/return
 1450 
 1451 test-return-with-wrong-type:
 1452     # . prologue
 1453     55/push-ebp
 1454     89/<- %ebp 4/r32/esp
 1455     # setup
 1456     (clear-stream _test-input-stream)
 1457     (clear-stream $_test-input-buffered-file->buffer)
 1458     (clear-stream _test-output-stream)
 1459     (clear-stream $_test-output-buffered-file->buffer)
 1460     (clear-stream _test-error-stream)
 1461     (clear-stream $_test-error-buffered-file->buffer)
 1462     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1463     68/push 0/imm32
 1464     68/push 0/imm32
 1465     89/<- %edx 4/r32/esp
 1466     (tailor-exit-descriptor %edx 0x10)
 1467     #
 1468     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1469     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
 1470     (write _test-input-stream "  return x\n")
 1471     (write _test-input-stream "}\n")
 1472     # convert
 1473     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1474     # registers except esp clobbered at this point
 1475     # restore ed
 1476     89/<- %edx 4/r32/esp
 1477     (flush _test-output-buffered-file)
 1478     (flush _test-error-buffered-file)
 1479 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1485     # check output
 1486     (check-stream-equal _test-output-stream  ""  "F - test-return-with-wrong-type: output should be empty")
 1487     (check-next-stream-line-equal _test-error-stream  "fn foo: return: 'x' has the wrong type"  "F - test-return-with-wrong-type: error message")
 1488     # check that stop(1) was called
 1489     (check-ints-equal *(edx+4) 2 "F - test-return-with-wrong-type: exit status")
 1490     # don't restore from ebp
 1491     81 0/subop/add %esp 8/imm32
 1492     # . epilogue
 1493     5d/pop-to-ebp
 1494     c3/return
 1495 
 1496 test-missing-return:
 1497     # . prologue
 1498     55/push-ebp
 1499     89/<- %ebp 4/r32/esp
 1500     # setup
 1501     (clear-stream _test-input-stream)
 1502     (clear-stream $_test-input-buffered-file->buffer)
 1503     (clear-stream _test-output-stream)
 1504     (clear-stream $_test-output-buffered-file->buffer)
 1505     (clear-stream _test-error-stream)
 1506     (clear-stream $_test-error-buffered-file->buffer)
 1507     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1508     68/push 0/imm32
 1509     68/push 0/imm32
 1510     89/<- %edx 4/r32/esp
 1511     (tailor-exit-descriptor %edx 0x10)
 1512     #
 1513     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1514     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
 1515     (write _test-input-stream "}\n")
 1516     # convert
 1517     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1518     # registers except esp clobbered at this point
 1519     # restore ed
 1520     89/<- %edx 4/r32/esp
 1521     (flush _test-output-buffered-file)
 1522     (flush _test-error-buffered-file)
 1523 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1529     # check output
 1530     (check-stream-equal _test-output-stream  ""  "F - test-missing-return: output should be empty")
 1531     (check-next-stream-line-equal _test-error-stream  "fn foo: final statement should be a 'return'"  "F - test-missing-return: error message")
 1532     # check that stop(1) was called
 1533     (check-ints-equal *(edx+4) 2 "F - test-missing-return: exit status")
 1534     # don't restore from ebp
 1535     81 0/subop/add %esp 8/imm32
 1536     # . epilogue
 1537     5d/pop-to-ebp
 1538     c3/return
 1539 
 1540 test-early-exit-without-return:
 1541     # . prologue
 1542     55/push-ebp
 1543     89/<- %ebp 4/r32/esp
 1544     # setup
 1545     (clear-stream _test-input-stream)
 1546     (clear-stream $_test-input-buffered-file->buffer)
 1547     (clear-stream _test-output-stream)
 1548     (clear-stream $_test-output-buffered-file->buffer)
 1549     (clear-stream _test-error-stream)
 1550     (clear-stream $_test-error-buffered-file->buffer)
 1551     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1552     68/push 0/imm32
 1553     68/push 0/imm32
 1554     89/<- %edx 4/r32/esp
 1555     (tailor-exit-descriptor %edx 0x10)
 1556     #
 1557     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1558     (write _test-input-stream "  break\n")
 1559     (write _test-input-stream "  return 0\n")
 1560     (write _test-input-stream "}\n")
 1561     # convert
 1562     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1563     # registers except esp clobbered at this point
 1564     # restore ed
 1565     89/<- %edx 4/r32/esp
 1566     (flush _test-output-buffered-file)
 1567     (flush _test-error-buffered-file)
 1568 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1574     # check output
 1575     (check-stream-equal _test-output-stream  ""  "F - test-early-exit-without-return: output should be empty")
 1576     (check-next-stream-line-equal _test-error-stream  "fn foo has outputs, so you cannot 'break' out of the outermost block. Use 'return'."  "F - test-early-exit-without-return: error message")
 1577     # check that stop(1) was called
 1578     (check-ints-equal *(edx+4) 2 "F - test-early-exit-without-return: exit status")
 1579     # don't restore from ebp
 1580     81 0/subop/add %esp 8/imm32
 1581     # . epilogue
 1582     5d/pop-to-ebp
 1583     c3/return
 1584 
 1585 test-return-with-too-few-inouts:
 1586     # . prologue
 1587     55/push-ebp
 1588     89/<- %ebp 4/r32/esp
 1589     # setup
 1590     (clear-stream _test-input-stream)
 1591     (clear-stream $_test-input-buffered-file->buffer)
 1592     (clear-stream _test-output-stream)
 1593     (clear-stream $_test-output-buffered-file->buffer)
 1594     (clear-stream _test-error-stream)
 1595     (clear-stream $_test-error-buffered-file->buffer)
 1596     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1597     68/push 0/imm32
 1598     68/push 0/imm32
 1599     89/<- %edx 4/r32/esp
 1600     (tailor-exit-descriptor %edx 0x10)
 1601     #
 1602     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1603     (write _test-input-stream "  return\n")
 1604     (write _test-input-stream "}\n")
 1605     # convert
 1606     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1607     # registers except esp clobbered at this point
 1608     # restore ed
 1609     89/<- %edx 4/r32/esp
 1610     (flush _test-output-buffered-file)
 1611     (flush _test-error-buffered-file)
 1612 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1618     # check output
 1619     (check-stream-equal _test-output-stream  ""  "F - test-return-with-too-few-inouts: output should be empty")
 1620     (check-next-stream-line-equal _test-error-stream  "fn foo: return: too few inouts"  "F - test-return-with-too-few-inouts: error message")
 1621     # check that stop(1) was called
 1622     (check-ints-equal *(edx+4) 2 "F - test-return-with-too-few-inouts: exit status")
 1623     # don't restore from ebp
 1624     81 0/subop/add %esp 8/imm32
 1625     # . epilogue
 1626     5d/pop-to-ebp
 1627     c3/return
 1628 
 1629 test-return-with-too-many-inouts:
 1630     # . prologue
 1631     55/push-ebp
 1632     89/<- %ebp 4/r32/esp
 1633     # setup
 1634     (clear-stream _test-input-stream)
 1635     (clear-stream $_test-input-buffered-file->buffer)
 1636     (clear-stream _test-output-stream)
 1637     (clear-stream $_test-output-buffered-file->buffer)
 1638     (clear-stream _test-error-stream)
 1639     (clear-stream $_test-error-buffered-file->buffer)
 1640     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1641     68/push 0/imm32
 1642     68/push 0/imm32
 1643     89/<- %edx 4/r32/esp
 1644     (tailor-exit-descriptor %edx 0x10)
 1645     #
 1646     (write _test-input-stream "fn foo -> _/eax: int {\n")
 1647     (write _test-input-stream "  return 0, 0\n")
 1648     (write _test-input-stream "}\n")
 1649     # convert
 1650     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1651     # registers except esp clobbered at this point
 1652     # restore ed
 1653     89/<- %edx 4/r32/esp
 1654     (flush _test-output-buffered-file)
 1655     (flush _test-error-buffered-file)
 1656 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1662     # check output
 1663     (check-stream-equal _test-output-stream  ""  "F - test-return-with-too-many-inouts: output should be empty")
 1664     (check-next-stream-line-equal _test-error-stream  "fn foo: return: too many inouts"  "F - test-return-with-too-many-inouts: error message")
 1665     # check that stop(1) was called
 1666     (check-ints-equal *(edx+4) 2 "F - test-return-with-too-many-inouts: exit status")
 1667     # don't restore from ebp
 1668     81 0/subop/add %esp 8/imm32
 1669     # . epilogue
 1670     5d/pop-to-ebp
 1671     c3/return
 1672 
 1673 test-return-unavailable-value:
 1674     # . prologue
 1675     55/push-ebp
 1676     89/<- %ebp 4/r32/esp
 1677     # setup
 1678     (clear-stream _test-input-stream)
 1679     (clear-stream $_test-input-buffered-file->buffer)
 1680     (clear-stream _test-output-stream)
 1681     (clear-stream $_test-output-buffered-file->buffer)
 1682     (clear-stream _test-error-stream)
 1683     (clear-stream $_test-error-buffered-file->buffer)
 1684     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1685     68/push 0/imm32
 1686     68/push 0/imm32
 1687     89/<- %edx 4/r32/esp
 1688     (tailor-exit-descriptor %edx 0x10)
 1689     #
 1690     (write _test-input-stream "fn foo -> _/eax: int, _/ecx: int {\n")
 1691     (write _test-input-stream "  var x/eax: int <- copy 0\n")
 1692     (write _test-input-stream "  var y/ecx: int <- copy 0\n")
 1693     (write _test-input-stream "  return y, x\n")
 1694     (write _test-input-stream "}\n")
 1695     # convert
 1696     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1697     # registers except esp clobbered at this point
 1698     # restore ed
 1699     89/<- %edx 4/r32/esp
 1700     (flush _test-output-buffered-file)
 1701     (flush _test-error-buffered-file)
 1702 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1708     # check output
 1709     (check-stream-equal _test-output-stream  ""  "F - test-return-unavailable-value: output should be empty")
 1710     (check-next-stream-line-equal _test-error-stream  "fn foo: return: 'x' is no longer available"  "F - test-return-unavailable-value: error message")
 1711     # check that stop(1) was called
 1712     (check-ints-equal *(edx+4) 2 "F - test-return-unavailable-value: exit status")
 1713     # don't restore from ebp
 1714     81 0/subop/add %esp 8/imm32
 1715     # . epilogue
 1716     5d/pop-to-ebp
 1717     c3/return
 1718 
 1719 test-convert-return-with-duplicate-values:
 1720     # . prologue
 1721     55/push-ebp
 1722     89/<- %ebp 4/r32/esp
 1723     # setup
 1724     (clear-stream _test-input-stream)
 1725     (clear-stream $_test-input-buffered-file->buffer)
 1726     (clear-stream _test-output-stream)
 1727     (clear-stream $_test-output-buffered-file->buffer)
 1728     #
 1729     (write _test-input-stream "fn foo -> _/eax: int, _/ecx: int {\n")
 1730     (write _test-input-stream "  var x/eax: int <- copy 0x34\n")
 1731     (write _test-input-stream "  return x, x\n")
 1732     (write _test-input-stream "}\n")
 1733     # convert
 1734     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1735     (flush _test-output-buffered-file)
 1736 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1742     # check output
 1743     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-return-with-duplicate-values/0")
 1744     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-return-with-duplicate-values/1")
 1745     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-return-with-duplicate-values/2")
 1746     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-return-with-duplicate-values/3")
 1747     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-return-with-duplicate-values/4")
 1748     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-return-with-duplicate-values/5")
 1749     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-return-with-duplicate-values/6")
 1750     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0x34/imm32"  "F - test-convert-return-with-duplicate-values/7")
 1751     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32"  "F - test-convert-return-with-duplicate-values/8")
 1752     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000001/r32"  "F - test-convert-return-with-duplicate-values/9")
 1753     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-return-with-duplicate-values/10")
 1754     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-return-with-duplicate-values/11")
 1755     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-return-with-duplicate-values/12")
 1756     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-return-with-duplicate-values/13")
 1757     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-return-with-duplicate-values/14")
 1758     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-return-with-duplicate-values/15")
 1759     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-return-with-duplicate-values/16")
 1760     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-return-with-duplicate-values/17")
 1761     # . epilogue
 1762     89/<- %esp 5/r32/ebp
 1763     5d/pop-to-ebp
 1764     c3/return
 1765 
 1766 test-convert-return-with-duplicate-values-2:
 1767     # . prologue
 1768     55/push-ebp
 1769     89/<- %ebp 4/r32/esp
 1770     # setup
 1771     (clear-stream _test-input-stream)
 1772     (clear-stream $_test-input-buffered-file->buffer)
 1773     (clear-stream _test-output-stream)
 1774     (clear-stream $_test-output-buffered-file->buffer)
 1775     #
 1776     (write _test-input-stream "fn foo -> _/eax: int, _/ecx: int {\n")
 1777     (write _test-input-stream "  var x/ecx: int <- copy 0x34\n")
 1778     (write _test-input-stream "  return x, x\n")
 1779     (write _test-input-stream "}\n")
 1780     # convert
 1781     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1782     (flush _test-output-buffered-file)
 1783 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1789     # check output
 1790     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-return-with-duplicate-values-2/0")
 1791     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-return-with-duplicate-values-2/1")
 1792     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-return-with-duplicate-values-2/2")
 1793     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-return-with-duplicate-values-2/3")
 1794     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-return-with-duplicate-values-2/4")
 1795     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-return-with-duplicate-values-2/5")
 1796     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-return-with-duplicate-values-2/6")
 1797     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0x34/imm32"  "F - test-convert-return-with-duplicate-values-2/7")
 1798     (check-next-stream-line-equal _test-output-stream "    8b/-> %ecx 0x00000000/r32"  "F - test-convert-return-with-duplicate-values-2/8")
 1799     (check-next-stream-line-equal _test-output-stream "    8b/-> %ecx 0x00000001/r32"  "F - test-convert-return-with-duplicate-values-2/9")
 1800     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-return-with-duplicate-values-2/10")
 1801     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-return-with-duplicate-values-2/11")
 1802     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-return-with-duplicate-values-2/12")
 1803     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-return-with-duplicate-values-2/13")
 1804     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-return-with-duplicate-values-2/14")
 1805     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-return-with-duplicate-values-2/15")
 1806     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-return-with-duplicate-values-2/16")
 1807     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-return-with-duplicate-values-2/17")
 1808     # . epilogue
 1809     89/<- %esp 5/r32/ebp
 1810     5d/pop-to-ebp
 1811     c3/return
 1812 
 1813 test-stmt-with-unknown-var:
 1814     # . prologue
 1815     55/push-ebp
 1816     89/<- %ebp 4/r32/esp
 1817     # setup
 1818     (clear-stream _test-input-stream)
 1819     (clear-stream $_test-input-buffered-file->buffer)
 1820     (clear-stream _test-output-stream)
 1821     (clear-stream $_test-output-buffered-file->buffer)
 1822     (clear-stream _test-error-stream)
 1823     (clear-stream $_test-error-buffered-file->buffer)
 1824     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1825     68/push 0/imm32
 1826     68/push 0/imm32
 1827     89/<- %edx 4/r32/esp
 1828     (tailor-exit-descriptor %edx 0x10)
 1829     #
 1830     (write _test-input-stream "fn foo {\n")
 1831     (write _test-input-stream "  x <- copy 0x34\n")
 1832     (write _test-input-stream "}\n")
 1833     # convert
 1834     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1835     # registers except esp clobbered at this point
 1836     # restore ed
 1837     89/<- %edx 4/r32/esp
 1838     (flush _test-output-buffered-file)
 1839     (flush _test-error-buffered-file)
 1840 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1846     # check output
 1847     (check-stream-equal _test-output-stream  ""  "F - test-stmt-with-unknown-var: output should be empty")
 1848     (check-next-stream-line-equal _test-error-stream  "fn foo: unknown variable 'x'"  "F - test-stmt-with-unknown-var: error message")
 1849     # check that stop(1) was called
 1850     (check-ints-equal *(edx+4) 2 "F - test-stmt-with-unknown-var: exit status")
 1851     # don't restore from ebp
 1852     81 0/subop/add %esp 8/imm32
 1853     # . epilogue
 1854     5d/pop-to-ebp
 1855     c3/return
 1856 
 1857 test-stmt-with-invalid-identifier:
 1858     # . prologue
 1859     55/push-ebp
 1860     89/<- %ebp 4/r32/esp
 1861     # setup
 1862     (clear-stream _test-input-stream)
 1863     (clear-stream $_test-input-buffered-file->buffer)
 1864     (clear-stream _test-output-stream)
 1865     (clear-stream $_test-output-buffered-file->buffer)
 1866     (clear-stream _test-error-stream)
 1867     (clear-stream $_test-error-buffered-file->buffer)
 1868     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1869     68/push 0/imm32
 1870     68/push 0/imm32
 1871     89/<- %edx 4/r32/esp
 1872     (tailor-exit-descriptor %edx 0x10)
 1873     #
 1874     (write _test-input-stream "fn foo {\n")
 1875     (write _test-input-stream "  1 <- copy 0x34\n")
 1876     (write _test-input-stream "}\n")
 1877     # convert
 1878     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1879     # registers except esp clobbered at this point
 1880     # restore ed
 1881     89/<- %edx 4/r32/esp
 1882     (flush _test-output-buffered-file)
 1883     (flush _test-error-buffered-file)
 1884 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1890     # check output
 1891     (check-stream-equal _test-output-stream  ""  "F - test-stmt-with-invalid-identifier: output should be empty")
 1892     (check-next-stream-line-equal _test-error-stream  "fn foo: invalid identifier '1'"  "F - test-stmt-with-invalid-identifier: error message")
 1893     # check that stop(1) was called
 1894     (check-ints-equal *(edx+4) 2 "F - test-stmt-with-invalid-identifier: exit status")
 1895     # don't restore from ebp
 1896     81 0/subop/add %esp 8/imm32
 1897     # . epilogue
 1898     5d/pop-to-ebp
 1899     c3/return
 1900 
 1901 test-stmt-with-deref-var:
 1902     # . prologue
 1903     55/push-ebp
 1904     89/<- %ebp 4/r32/esp
 1905     # setup
 1906     (clear-stream _test-input-stream)
 1907     (clear-stream $_test-input-buffered-file->buffer)
 1908     (clear-stream _test-output-stream)
 1909     (clear-stream $_test-output-buffered-file->buffer)
 1910     (clear-stream _test-error-stream)
 1911     (clear-stream $_test-error-buffered-file->buffer)
 1912     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 1913     68/push 0/imm32
 1914     68/push 0/imm32
 1915     89/<- %edx 4/r32/esp
 1916     (tailor-exit-descriptor %edx 0x10)
 1917     #
 1918     (write _test-input-stream "fn foo {\n")
 1919     (write _test-input-stream "  *x <- copy 0x34\n")
 1920     (write _test-input-stream "}\n")
 1921     # convert
 1922     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 1923     # registers except esp clobbered at this point
 1924     # restore ed
 1925     89/<- %edx 4/r32/esp
 1926     (flush _test-output-buffered-file)
 1927     (flush _test-error-buffered-file)
 1928 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1934     # check output
 1935     (check-stream-equal _test-output-stream  ""  "F - test-stmt-with-deref-var: output should be empty")
 1936     (check-next-stream-line-equal _test-error-stream  "fn foo: output '*x' should write to a register, and therefore cannot be dereferenced"  "F - test-stmt-with-deref-var: error message")
 1937     # check that stop(1) was called
 1938     (check-ints-equal *(edx+4) 2 "F - test-stmt-with-deref-var: exit status")
 1939     # don't restore from ebp
 1940     81 0/subop/add %esp 8/imm32
 1941     # . epilogue
 1942     5d/pop-to-ebp
 1943     c3/return
 1944 
 1945 test-convert-function-with-literal-arg:
 1946     # . prologue
 1947     55/push-ebp
 1948     89/<- %ebp 4/r32/esp
 1949     # setup
 1950     (clear-stream _test-input-stream)
 1951     (clear-stream $_test-input-buffered-file->buffer)
 1952     (clear-stream _test-output-stream)
 1953     (clear-stream $_test-output-buffered-file->buffer)
 1954     #
 1955     (write _test-input-stream "fn foo a: int, b: int -> _/eax: int {\n")
 1956     (write _test-input-stream "  var result/eax: int <- copy a\n")
 1957     (write _test-input-stream "  result <- add 1\n")
 1958     (write _test-input-stream "  return result\n")
 1959     (write _test-input-stream "}\n")
 1960     # convert
 1961     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 1962     (flush _test-output-buffered-file)
 1963 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1969     # check output
 1970     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-literal-arg/0")
 1971     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-literal-arg/1")
 1972     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-literal-arg/2")
 1973     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-literal-arg/3")
 1974     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-literal-arg/4")
 1975     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-literal-arg/5")
 1976     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-with-literal-arg/6")
 1977     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-function-with-literal-arg/7")
 1978     (check-next-stream-line-equal _test-output-stream "    05/add-to-eax 1/imm32"  "F - test-convert-function-with-literal-arg/8")
 1979     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32" "F - test-convert-function-with-literal-arg/9")
 1980     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-with-literal-arg/10")
 1981     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-literal-arg/11")
 1982     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-literal-arg/12")
 1983     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-literal-arg/13")
 1984     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-literal-arg/14")
 1985     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-literal-arg/15")
 1986     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-literal-arg/16")
 1987     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-literal-arg/17")
 1988     # . epilogue
 1989     89/<- %esp 5/r32/ebp
 1990     5d/pop-to-ebp
 1991     c3/return
 1992 
 1993 test-convert-function-with-literal-arg-2:
 1994     # . prologue
 1995     55/push-ebp
 1996     89/<- %ebp 4/r32/esp
 1997     # setup
 1998     (clear-stream _test-input-stream)
 1999     (clear-stream $_test-input-buffered-file->buffer)
 2000     (clear-stream _test-output-stream)
 2001     (clear-stream $_test-output-buffered-file->buffer)
 2002     #
 2003     (write _test-input-stream "fn foo a: int, b: int -> _/ebx: int {\n")
 2004     (write _test-input-stream "  var result/ebx: int <- copy a\n")
 2005     (write _test-input-stream "  result <- add 1\n")
 2006     (write _test-input-stream "  return result\n")
 2007     (write _test-input-stream "}\n")
 2008     # convert
 2009     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2010     (flush _test-output-buffered-file)
 2011 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2017     # check output
 2018     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-literal-arg-2/0")
 2019     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-literal-arg-2/1")
 2020     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-literal-arg-2/2")
 2021     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-literal-arg-2/3")
 2022     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-literal-arg-2/4")
 2023     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-literal-arg-2/5")
 2024     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ebx"  "F - test-convert-function-with-literal-arg-2/6")
 2025     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000003/r32"  "F - test-convert-function-with-literal-arg-2/7")
 2026     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %ebx 1/imm32"  "F - test-convert-function-with-literal-arg-2/8")
 2027     (check-next-stream-line-equal _test-output-stream "    8b/-> %ebx 0x00000003/r32" "F - test-convert-function-with-literal-arg-2/9")
 2028     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-with-literal-arg-2/10")
 2029     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-literal-arg-2/11")
 2030     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-literal-arg-2/12")
 2031     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-literal-arg-2/13")
 2032     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-literal-arg-2/14")
 2033     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-literal-arg-2/15")
 2034     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-literal-arg-2/16")
 2035     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-literal-arg-2/17")
 2036     # . epilogue
 2037     89/<- %esp 5/r32/ebp
 2038     5d/pop-to-ebp
 2039     c3/return
 2040 
 2041 test-convert-function-call-with-literal-arg:
 2042     # . prologue
 2043     55/push-ebp
 2044     89/<- %ebp 4/r32/esp
 2045     # setup
 2046     (clear-stream _test-input-stream)
 2047     (clear-stream $_test-input-buffered-file->buffer)
 2048     (clear-stream _test-output-stream)
 2049     (clear-stream $_test-output-buffered-file->buffer)
 2050     #
 2051     (write _test-input-stream "fn main -> _/ebx: int {\n")
 2052     (write _test-input-stream "  var result/eax: int <- do-add 3 4\n")
 2053     (write _test-input-stream "  return result\n")
 2054     (write _test-input-stream "}\n")
 2055     (write _test-input-stream "fn do-add a: int, b: int -> _/eax: int {\n")
 2056     (write _test-input-stream "  var result/eax: int <- copy a\n")
 2057     (write _test-input-stream "  result <- add b\n")
 2058     (write _test-input-stream "  return result\n")
 2059     (write _test-input-stream "}\n")
 2060     # convert
 2061     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2062     (flush _test-output-buffered-file)
 2063 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2069     # check output
 2070     (check-next-stream-line-equal _test-output-stream "main:"                   "F - test-convert-function-call-with-literal-arg/0")
 2071     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-literal-arg/1")
 2072     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-literal-arg/2")
 2073     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-literal-arg/3")
 2074     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-literal-arg/4")
 2075     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:loop:"  "F - test-convert-function-call-with-literal-arg/5")
 2076     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-call-with-literal-arg/6")
 2077     (check-next-stream-line-equal _test-output-stream "    (do-add 3 4)"        "F - test-convert-function-call-with-literal-arg/7")
 2078     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/8")
 2079     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-function-with-local-var-in-reg/9")
 2080     (check-next-stream-line-equal _test-output-stream "    e9/jump $main:0x00000001:break/disp32"  "F - test-convert-function-call-with-literal-arg/10")
 2081     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-literal-arg/11")
 2082     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:break:" "F - test-convert-function-call-with-literal-arg/12")
 2083     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-literal-arg/13")
 2084     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-literal-arg/14")
 2085     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-literal-arg/15")
 2086     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-literal-arg/16")
 2087     (check-next-stream-line-equal _test-output-stream "do-add:"                 "F - test-convert-function-call-with-literal-arg/17")
 2088     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-literal-arg/18")
 2089     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-literal-arg/19")
 2090     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-literal-arg/20")
 2091     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-literal-arg/21")
 2092     (check-next-stream-line-equal _test-output-stream "$do-add:0x00000002:loop:"  "F - test-convert-function-call-with-literal-arg/22")
 2093     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-call-with-literal-arg/23")
 2094     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-function-call-with-literal-arg/24")
 2095     (check-next-stream-line-equal _test-output-stream "    03/add *(ebp+0x0000000c) 0x00000000/r32"  "F - test-convert-function-call-with-literal-arg/25")
 2096     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32" "F - test-convert-function-call-with-literal-arg/26")
 2097     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-call-with-literal-arg/27")
 2098     (check-next-stream-line-equal _test-output-stream "    e9/jump $do-add:0x00000002:break/disp32"  "F - test-convert-function-call-with-literal-arg/28")
 2099     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-literal-arg/29")
 2100     (check-next-stream-line-equal _test-output-stream "$do-add:0x00000002:break:"  "F - test-convert-function-call-with-literal-arg/30")
 2101     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-literal-arg/31")
 2102     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-literal-arg/32")
 2103     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-literal-arg/33")
 2104     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-literal-arg/34")
 2105     # . epilogue
 2106     89/<- %esp 5/r32/ebp
 2107     5d/pop-to-ebp
 2108     c3/return
 2109 
 2110 test-convert-function-call-with-literal-string-arg:
 2111     # . prologue
 2112     55/push-ebp
 2113     89/<- %ebp 4/r32/esp
 2114     # setup
 2115     (clear-stream _test-input-stream)
 2116     (clear-stream $_test-input-buffered-file->buffer)
 2117     (clear-stream _test-output-stream)
 2118     (clear-stream $_test-output-buffered-file->buffer)
 2119     #
 2120     (write _test-input-stream "fn foo {\n")
 2121     (write _test-input-stream "  string-func \"abc\"\n")
 2122     (write _test-input-stream "}\n")
 2123     (write _test-input-stream "sig string-func in: (addr array byte)\n")
 2124     # convert
 2125     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2126     # no errors
 2127     # not bothering checking output
 2128     # . epilogue
 2129     89/<- %esp 5/r32/ebp
 2130     5d/pop-to-ebp
 2131     c3/return
 2132 
 2133 test-convert-function-call-with-null-addr:
 2134     # . prologue
 2135     55/push-ebp
 2136     89/<- %ebp 4/r32/esp
 2137     # setup
 2138     (clear-stream _test-input-stream)
 2139     (clear-stream $_test-input-buffered-file->buffer)
 2140     (clear-stream _test-output-stream)
 2141     (clear-stream $_test-output-buffered-file->buffer)
 2142     #
 2143     (write _test-input-stream "fn foo {\n")
 2144     (write _test-input-stream "  bar 0\n")
 2145     (write _test-input-stream "}\n")
 2146     (write _test-input-stream "sig bar in: (addr int)\n")
 2147     # convert
 2148     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2149     # no errors
 2150     # not bothering checking output
 2151     # . epilogue
 2152     89/<- %esp 5/r32/ebp
 2153     5d/pop-to-ebp
 2154     c3/return
 2155 
 2156 test-convert-function-call-with-signature:
 2157     # . prologue
 2158     55/push-ebp
 2159     89/<- %ebp 4/r32/esp
 2160     # setup
 2161     (clear-stream _test-input-stream)
 2162     (clear-stream $_test-input-buffered-file->buffer)
 2163     (clear-stream _test-output-stream)
 2164     (clear-stream $_test-output-buffered-file->buffer)
 2165     #
 2166     (write _test-input-stream "fn main -> _/ebx: int {\n")
 2167     (write _test-input-stream "  var result/eax: int <- do-add 3 4\n")
 2168     (write _test-input-stream "  return result\n")
 2169     (write _test-input-stream "}\n")
 2170     (write _test-input-stream "sig do-add a: int, b: int -> _/eax: int\n")
 2171     # convert
 2172     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2173     (flush _test-output-buffered-file)
 2174 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2180     # check output
 2181     (check-next-stream-line-equal _test-output-stream "main:"                   "F - test-convert-function-call-with-signature/0")
 2182     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-signature/1")
 2183     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-signature/2")
 2184     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-signature/3")
 2185     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-signature/4")
 2186     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:loop:"  "F - test-convert-function-call-with-signature/5")
 2187     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-call-with-literal-arg/6")
 2188     (check-next-stream-line-equal _test-output-stream "    (do-add 3 4)"        "F - test-convert-function-call-with-signature/6")
 2189     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/8")
 2190     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-function-with-local-var-in-reg/9")
 2191     (check-next-stream-line-equal _test-output-stream "    e9/jump $main:0x00000001:break/disp32"  "F - test-convert-function-call-with-literal-arg/10")
 2192     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-signature/7")
 2193     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:break:" "F - test-convert-function-call-with-signature/8")
 2194     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-signature/9")
 2195     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-signature/10")
 2196     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-signature/11")
 2197     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-signature/12")
 2198     # . epilogue
 2199     89/<- %esp 5/r32/ebp
 2200     5d/pop-to-ebp
 2201     c3/return
 2202 
 2203 test-convert-function-with-local-var-in-mem:
 2204     # . prologue
 2205     55/push-ebp
 2206     89/<- %ebp 4/r32/esp
 2207     # setup
 2208     (clear-stream _test-input-stream)
 2209     (clear-stream $_test-input-buffered-file->buffer)
 2210     (clear-stream _test-output-stream)
 2211     (clear-stream $_test-output-buffered-file->buffer)
 2212     #
 2213     (write _test-input-stream "fn foo {\n")
 2214     (write _test-input-stream "  var x: int\n")
 2215     (write _test-input-stream "  increment x\n")
 2216     (write _test-input-stream "}\n")
 2217     # convert
 2218     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2219     (flush _test-output-buffered-file)
 2220 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2226     # check output
 2227     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-mem/0")
 2228     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-mem/1")
 2229     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-mem/2")
 2230     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-mem/3")
 2231     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-mem/4")
 2232     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-mem/5")
 2233     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-in-mem/6")
 2234     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-local-var-in-mem/7")
 2235     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-local-var-in-mem/8")
 2236     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-mem/9")
 2237     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-mem/10")
 2238     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-mem/11")
 2239     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-mem/12")
 2240     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-mem/13")
 2241     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-mem/14")
 2242     # . epilogue
 2243     89/<- %esp 5/r32/ebp
 2244     5d/pop-to-ebp
 2245     c3/return
 2246 
 2247 test-convert-invalid-literal:
 2248     # . prologue
 2249     55/push-ebp
 2250     89/<- %ebp 4/r32/esp
 2251     # setup
 2252     (clear-stream _test-input-stream)
 2253     (clear-stream $_test-input-buffered-file->buffer)
 2254     (clear-stream _test-output-stream)
 2255     (clear-stream $_test-output-buffered-file->buffer)
 2256     (clear-stream _test-error-stream)
 2257     (clear-stream $_test-error-buffered-file->buffer)
 2258     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2259     68/push 0/imm32
 2260     68/push 0/imm32
 2261     89/<- %edx 4/r32/esp
 2262     (tailor-exit-descriptor %edx 0x10)
 2263     #
 2264     (write _test-input-stream "fn foo {\n")
 2265     (write _test-input-stream "  increment 1n\n")
 2266     (write _test-input-stream "}\n")
 2267     # convert
 2268     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2269     # registers except esp clobbered at this point
 2270     # restore ed
 2271     89/<- %edx 4/r32/esp
 2272     (flush _test-output-buffered-file)
 2273     (flush _test-error-buffered-file)
 2274 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2280     # check output
 2281     (check-stream-equal _test-output-stream  ""  "F - test-convert-invalid-literal: output should be empty")
 2282     (check-next-stream-line-equal _test-error-stream  "fn foo: variable '1n' cannot begin with a digit (or do you have a typo in a number?)"  "F - test-convert-invalid-literal: error message")
 2283     # check that stop(1) was called
 2284     (check-ints-equal *(edx+4) 2 "F - test-convert-invalid-literal: exit status")
 2285     # don't restore from ebp
 2286     81 0/subop/add %esp 8/imm32
 2287     # . epilogue
 2288     5d/pop-to-ebp
 2289     c3/return
 2290 
 2291 test-local-var-in-mem-has-no-initializer:
 2292     # . prologue
 2293     55/push-ebp
 2294     89/<- %ebp 4/r32/esp
 2295     # setup
 2296     (clear-stream _test-input-stream)
 2297     (clear-stream $_test-input-buffered-file->buffer)
 2298     (clear-stream _test-output-stream)
 2299     (clear-stream $_test-output-buffered-file->buffer)
 2300     (clear-stream _test-error-stream)
 2301     (clear-stream $_test-error-buffered-file->buffer)
 2302     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2303     68/push 0/imm32
 2304     68/push 0/imm32
 2305     89/<- %edx 4/r32/esp
 2306     (tailor-exit-descriptor %edx 0x10)
 2307     #
 2308     (write _test-input-stream "fn foo {\n")
 2309     (write _test-input-stream "  var x: int <- copy 0\n")
 2310     (write _test-input-stream "  increment x\n")
 2311     (write _test-input-stream "}\n")
 2312     # convert
 2313     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2314     # registers except esp clobbered at this point
 2315     # restore ed
 2316     89/<- %edx 4/r32/esp
 2317     (flush _test-output-buffered-file)
 2318     (flush _test-error-buffered-file)
 2319 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2325     # check output
 2326     (check-stream-equal _test-output-stream  ""  "F - test-var-in-mem-has-no-initializer: output should be empty")
 2327     (check-next-stream-line-equal _test-error-stream  "fn foo: var x: variables on the stack can't take an initializer"  "F - test-var-in-mem-has-no-initializer: error message")
 2328     # check that stop(1) was called
 2329     (check-ints-equal *(edx+4) 2 "F - test-var-in-mem-has-no-initializer: exit status")
 2330     # don't restore from ebp
 2331     81 0/subop/add %esp 8/imm32
 2332     # . epilogue
 2333     5d/pop-to-ebp
 2334     c3/return
 2335 
 2336 test-convert-function-with-local-var-with-compound-type-in-mem:
 2337     # . prologue
 2338     55/push-ebp
 2339     89/<- %ebp 4/r32/esp
 2340     # setup
 2341     (clear-stream _test-input-stream)
 2342     (clear-stream $_test-input-buffered-file->buffer)
 2343     (clear-stream _test-output-stream)
 2344     (clear-stream $_test-output-buffered-file->buffer)
 2345     #
 2346     (write _test-input-stream "fn foo {\n")
 2347     (write _test-input-stream "  var x: (addr int)\n")
 2348     (write _test-input-stream "  copy-to x, 0\n")
 2349     (write _test-input-stream "}\n")
 2350     # convert
 2351     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2352     (flush _test-output-buffered-file)
 2353 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2359     # check output
 2360     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-with-compound-type-in-mem/0")
 2361     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-with-compound-type-in-mem/1")
 2362     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-with-compound-type-in-mem/2")
 2363     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-with-compound-type-in-mem/3")
 2364     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-with-compound-type-in-mem/4")
 2365     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-with-compound-type-in-mem/5")
 2366     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-with-compound-type-in-mem/6")
 2367     (check-next-stream-line-equal _test-output-stream "    c7 0/subop/copy *(ebp+0xfffffffc) 0/imm32"  "F - test-convert-function-with-local-var-with-compound-type-in-mem/7")
 2368     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-local-var-with-compound-type-in-mem/8")
 2369     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-with-compound-type-in-mem/9")
 2370     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-with-compound-type-in-mem/10")
 2371     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-with-compound-type-in-mem/11")
 2372     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-with-compound-type-in-mem/12")
 2373     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-with-compound-type-in-mem/13")
 2374     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-with-compound-type-in-mem/14")
 2375     # . epilogue
 2376     89/<- %esp 5/r32/ebp
 2377     5d/pop-to-ebp
 2378     c3/return
 2379 
 2380 test-convert-function-with-local-var-in-reg:
 2381     # . prologue
 2382     55/push-ebp
 2383     89/<- %ebp 4/r32/esp
 2384     # setup
 2385     (clear-stream _test-input-stream)
 2386     (clear-stream $_test-input-buffered-file->buffer)
 2387     (clear-stream _test-output-stream)
 2388     (clear-stream $_test-output-buffered-file->buffer)
 2389     #
 2390     (write _test-input-stream "fn foo {\n")
 2391     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 2392     (write _test-input-stream "  x <- increment\n")
 2393     (write _test-input-stream "}\n")
 2394     # convert
 2395     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2396     (flush _test-output-buffered-file)
 2397 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2403     # check output
 2404     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-reg/0")
 2405     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-reg/1")
 2406     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-reg/2")
 2407     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-reg/3")
 2408     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-reg/4")
 2409     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-reg/5")
 2410     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-local-var-in-reg/6")
 2411     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-convert-function-with-local-var-in-reg/7")
 2412     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-convert-function-with-local-var-in-reg/8")
 2413     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-local-var-in-reg/9")
 2414     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-reg/10")
 2415     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-reg/11")
 2416     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-reg/12")
 2417     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-reg/13")
 2418     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-reg/14")
 2419     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-reg/15")
 2420     # . epilogue
 2421     89/<- %esp 5/r32/ebp
 2422     5d/pop-to-ebp
 2423     c3/return
 2424 
 2425 test-float-var-in-wrong-register:
 2426     # . prologue
 2427     55/push-ebp
 2428     89/<- %ebp 4/r32/esp
 2429     # setup
 2430     (clear-stream _test-input-stream)
 2431     (clear-stream $_test-input-buffered-file->buffer)
 2432     (clear-stream _test-output-stream)
 2433     (clear-stream $_test-output-buffered-file->buffer)
 2434     (clear-stream _test-error-stream)
 2435     (clear-stream $_test-error-buffered-file->buffer)
 2436     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2437     68/push 0/imm32
 2438     68/push 0/imm32
 2439     89/<- %edx 4/r32/esp
 2440     (tailor-exit-descriptor %edx 0x10)
 2441     #
 2442     (write _test-input-stream "fn foo {\n")
 2443     (write _test-input-stream "  var x/eax: int <- copy 0\n")
 2444     (write _test-input-stream "  var y/eax: float <- convert x\n")
 2445     (write _test-input-stream "}\n")
 2446     # convert
 2447     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2448     # registers except esp clobbered at this point
 2449     # restore ed
 2450     89/<- %edx 4/r32/esp
 2451     (flush _test-output-buffered-file)
 2452     (flush _test-error-buffered-file)
 2453 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2459     # check output
 2460     (check-stream-equal _test-output-stream  ""  "F - test-float-var-in-wrong-register: output should be empty")
 2461     (check-next-stream-line-equal _test-error-stream  "fn foo: float var 'y' should be in a floating-point register"  "F - test-float-var-in-wrong-register: error message")
 2462     # check that stop(1) was called
 2463     (check-ints-equal *(edx+4) 2 "F - test-float-var-in-wrong-register: exit status")
 2464     # don't restore from ebp
 2465     81 0/subop/add %esp 8/imm32
 2466     # . epilogue
 2467     5d/pop-to-ebp
 2468     c3/return
 2469 
 2470 test-non-float-var-in-wrong-register:
 2471     # . prologue
 2472     55/push-ebp
 2473     89/<- %ebp 4/r32/esp
 2474     # setup
 2475     (clear-stream _test-input-stream)
 2476     (clear-stream $_test-input-buffered-file->buffer)
 2477     (clear-stream _test-output-stream)
 2478     (clear-stream $_test-output-buffered-file->buffer)
 2479     (clear-stream _test-error-stream)
 2480     (clear-stream $_test-error-buffered-file->buffer)
 2481     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2482     68/push 0/imm32
 2483     68/push 0/imm32
 2484     89/<- %edx 4/r32/esp
 2485     (tailor-exit-descriptor %edx 0x10)
 2486     #
 2487     (write _test-input-stream "fn foo {\n")
 2488     (write _test-input-stream "  var x/xmm5: int <- copy 0\n")
 2489     (write _test-input-stream "}\n")
 2490     # convert
 2491     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2492     # registers except esp clobbered at this point
 2493     # restore ed
 2494     89/<- %edx 4/r32/esp
 2495     (flush _test-output-buffered-file)
 2496     (flush _test-error-buffered-file)
 2497 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2503     # check output
 2504     (check-stream-equal _test-output-stream  ""  "F - test-non-float-var-in-wrong-register: output should be empty")
 2505     (check-next-stream-line-equal _test-error-stream  "fn foo: non-float var 'x' should be in an integer register"  "F - test-non-float-var-in-wrong-register: error message")
 2506     # check that stop(1) was called
 2507     (check-ints-equal *(edx+4) 2 "F - test-non-float-var-in-wrong-register: exit status")
 2508     # don't restore from ebp
 2509     81 0/subop/add %esp 8/imm32
 2510     # . epilogue
 2511     5d/pop-to-ebp
 2512     c3/return
 2513 
 2514 test-convert-function-with-allocate:
 2515     # . prologue
 2516     55/push-ebp
 2517     89/<- %ebp 4/r32/esp
 2518     # setup
 2519     (clear-stream _test-input-stream)
 2520     (clear-stream $_test-input-buffered-file->buffer)
 2521     (clear-stream _test-output-stream)
 2522     (clear-stream $_test-output-buffered-file->buffer)
 2523     #
 2524     (write _test-input-stream "fn foo {\n")
 2525     (write _test-input-stream "  var x/ecx: (addr handle int) <- copy 0\n")
 2526     (write _test-input-stream "  allocate x\n")
 2527     (write _test-input-stream "}\n")
 2528     # convert
 2529     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2530     (flush _test-output-buffered-file)
 2531 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2537     # check output
 2538     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-allocate/0")
 2539     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-allocate/1")
 2540     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-allocate/2")
 2541     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-allocate/3")
 2542     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-allocate/4")
 2543     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-allocate/5")
 2544     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-allocate/6")
 2545     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-function-with-allocate/7")
 2546     (check-next-stream-line-equal _test-output-stream "    (allocate Heap 0x00000004 %ecx)"  "F - test-convert-function-with-allocate/8")  # 4 = size-of(int)
 2547     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-allocate/9")
 2548     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-allocate/10")
 2549     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-allocate/11")
 2550     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-allocate/12")
 2551     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-allocate/13")
 2552     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-allocate/14")
 2553     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-allocate/15")
 2554     # . epilogue
 2555     89/<- %esp 5/r32/ebp
 2556     5d/pop-to-ebp
 2557     c3/return
 2558 
 2559 test-initializer-in-hex:
 2560     # . prologue
 2561     55/push-ebp
 2562     89/<- %ebp 4/r32/esp
 2563     # setup
 2564     (clear-stream _test-input-stream)
 2565     (clear-stream $_test-input-buffered-file->buffer)
 2566     (clear-stream _test-output-stream)
 2567     (clear-stream $_test-output-buffered-file->buffer)
 2568     (clear-stream _test-error-stream)
 2569     (clear-stream $_test-error-buffered-file->buffer)
 2570     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2571     68/push 0/imm32
 2572     68/push 0/imm32
 2573     89/<- %edx 4/r32/esp
 2574     (tailor-exit-descriptor %edx 0x10)
 2575     #
 2576     (write _test-input-stream "fn foo {\n")
 2577     (write _test-input-stream "  var x/ecx: int <- copy 10\n")
 2578     (write _test-input-stream "}\n")
 2579     # convert
 2580     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2581     # registers except esp clobbered at this point
 2582     # restore ed
 2583     89/<- %edx 4/r32/esp
 2584     (flush _test-output-buffered-file)
 2585     (flush _test-error-buffered-file)
 2586 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2592     # check output
 2593     (check-stream-equal _test-output-stream  ""  "F - test-initializer-in-hex: output should be empty")
 2594     (check-next-stream-line-equal _test-error-stream  "literal integers are always hex in Mu; start '10' with a '0x' to be unambiguous, converting it to hexadecimal as necessary."  "F - test-initializer-in-hex: error message")
 2595     # check that stop(1) was called
 2596     (check-ints-equal *(edx+4) 2 "F - test-initializer-in-hex: exit status")
 2597     # don't restore from ebp
 2598     81 0/subop/add %esp 8/imm32
 2599     # . epilogue
 2600     5d/pop-to-ebp
 2601     c3/return
 2602 
 2603 test-convert-function-with-second-local-var-in-same-reg:
 2604     # . prologue
 2605     55/push-ebp
 2606     89/<- %ebp 4/r32/esp
 2607     # setup
 2608     (clear-stream _test-input-stream)
 2609     (clear-stream $_test-input-buffered-file->buffer)
 2610     (clear-stream _test-output-stream)
 2611     (clear-stream $_test-output-buffered-file->buffer)
 2612     #
 2613     (write _test-input-stream "fn foo {\n")
 2614     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 2615     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
 2616     (write _test-input-stream "  y <- increment\n")
 2617     (write _test-input-stream "}\n")
 2618     # convert
 2619     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2620     (flush _test-output-buffered-file)
 2621 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2627     # check output
 2628     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-second-local-var-in-same-reg/0")
 2629     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-second-local-var-in-same-reg/1")
 2630     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-second-local-var-in-same-reg/2")
 2631     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-second-local-var-in-same-reg/3")
 2632     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-second-local-var-in-same-reg/4")
 2633     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-second-local-var-in-same-reg/5")
 2634     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-second-local-var-in-same-reg/6")
 2635     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-convert-function-with-second-local-var-in-same-reg/7")
 2636     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 4/imm32"  "F - test-convert-function-with-second-local-var-in-same-reg/8")
 2637     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-convert-function-with-second-local-var-in-same-reg/9")
 2638     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-second-local-var-in-same-reg/10")
 2639     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-second-local-var-in-same-reg/11")
 2640     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-second-local-var-in-same-reg/12")
 2641     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-second-local-var-in-same-reg/13")
 2642     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-second-local-var-in-same-reg/14")
 2643     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-second-local-var-in-same-reg/15")
 2644     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-second-local-var-in-same-reg/16")
 2645     # . epilogue
 2646     89/<- %esp 5/r32/ebp
 2647     5d/pop-to-ebp
 2648     c3/return
 2649 
 2650 test-read-clobbered-reg-var:
 2651     # . prologue
 2652     55/push-ebp
 2653     89/<- %ebp 4/r32/esp
 2654     # setup
 2655     (clear-stream _test-input-stream)
 2656     (clear-stream $_test-input-buffered-file->buffer)
 2657     (clear-stream _test-output-stream)
 2658     (clear-stream $_test-output-buffered-file->buffer)
 2659     (clear-stream _test-error-stream)
 2660     (clear-stream $_test-error-buffered-file->buffer)
 2661     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)  # bytes of args in call to convert-mu
 2662     68/push 0/imm32
 2663     68/push 0/imm32
 2664     89/<- %edx 4/r32/esp
 2665     (tailor-exit-descriptor %edx 0x10)
 2666     #
 2667     (write _test-input-stream "fn foo {\n")
 2668     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 2669     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
 2670     (write _test-input-stream "  x <- increment\n")
 2671     (write _test-input-stream "}\n")
 2672     # convert
 2673     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2674     # registers except esp clobbered at this point
 2675     # restore ed
 2676     89/<- %edx 4/r32/esp
 2677     (flush _test-output-buffered-file)
 2678     (flush _test-error-buffered-file)
 2679 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2685     # check output
 2686     (check-stream-equal _test-output-stream  ""  "F - test-read-clobbered-reg-var: output should be empty")
 2687     (check-next-stream-line-equal _test-error-stream  "fn foo: register ecx reads var 'x' after writing var 'y'"  "F - test-read-clobbered-reg-var: error message")
 2688     # check that stop(1) was called
 2689     (check-ints-equal *(edx+4) 2 "F - test-read-clobbered-reg-var: exit status")
 2690     # don't restore from ebp
 2691     81 0/subop/add %esp 8/imm32
 2692     # . epilogue
 2693     5d/pop-to-ebp
 2694     c3/return
 2695 
 2696 test-overlapping-int-fp-registers:
 2697     # . prologue
 2698     55/push-ebp
 2699     89/<- %ebp 4/r32/esp
 2700     # setup
 2701     (clear-stream _test-input-stream)
 2702     (clear-stream $_test-input-buffered-file->buffer)
 2703     (clear-stream _test-output-stream)
 2704     (clear-stream $_test-output-buffered-file->buffer)
 2705     (clear-stream _test-error-stream)
 2706     (clear-stream $_test-error-buffered-file->buffer)
 2707     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)  # bytes of args in call to convert-mu
 2708     68/push 0/imm32
 2709     68/push 0/imm32
 2710     89/<- %edx 4/r32/esp
 2711     (tailor-exit-descriptor %edx 0x10)
 2712     #
 2713     (write _test-input-stream "fn foo {\n")
 2714     (write _test-input-stream "  var x/eax: int <- copy 3\n")
 2715     (write _test-input-stream "  var y/xmm0: float <- convert x\n")
 2716     (write _test-input-stream "  x <- increment\n")
 2717     (write _test-input-stream "}\n")
 2718     # convert
 2719     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2720     # registers except esp clobbered at this point
 2721     # restore ed
 2722     89/<- %edx 4/r32/esp
 2723     (flush _test-output-buffered-file)
 2724     (flush _test-error-buffered-file)
 2725 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2731     # no errors
 2732     (check-next-stream-line-equal _test-error-stream  ""  "F - test-overlapping-int-fp-registers: error message")
 2733     # don't bother checking the generated code
 2734     # don't restore from ebp
 2735     81 0/subop/add %esp 8/imm32
 2736     # . epilogue
 2737     5d/pop-to-ebp
 2738     c3/return
 2739 
 2740 test-convert-function-call:
 2741     # . prologue
 2742     55/push-ebp
 2743     89/<- %ebp 4/r32/esp
 2744     # setup
 2745     (clear-stream _test-input-stream)
 2746     (clear-stream $_test-input-buffered-file->buffer)
 2747     (clear-stream _test-output-stream)
 2748     (clear-stream $_test-output-buffered-file->buffer)
 2749     #
 2750     (write _test-input-stream "fn main -> _/ebx: int {\n")
 2751     (write _test-input-stream "  var result/ebx: int <- foo\n")
 2752     (write _test-input-stream "  return result\n")
 2753     (write _test-input-stream "}\n")
 2754     (write _test-input-stream "fn foo -> _/ebx: int {\n")
 2755     (write _test-input-stream "  var result/ebx: int <- copy 3\n")
 2756     (write _test-input-stream "  return result\n")
 2757     (write _test-input-stream "}\n")
 2758     # convert
 2759     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2760     (flush _test-output-buffered-file)
 2761 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2767     # check output
 2768     (check-next-stream-line-equal _test-output-stream "main:"                   "F - test-convert-function-call/0")
 2769     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call/1")
 2770     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call/2")
 2771     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call/3")
 2772     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call/4")
 2773     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:loop:"  "F - test-convert-function-call/5")
 2774     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ebx"  "F - test-convert-function-call-with-literal-arg/6")
 2775     (check-next-stream-line-equal _test-output-stream "    (foo)"               "F - test-convert-function-call/6")
 2776     (check-next-stream-line-equal _test-output-stream "    8b/-> %ebx 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/8")
 2777     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-call-with-literal-arg/27")
 2778     (check-next-stream-line-equal _test-output-stream "    e9/jump $main:0x00000001:break/disp32"  "F - test-convert-function-call-with-literal-arg/10")
 2779     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call/7")
 2780     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:break:" "F - test-convert-function-call/8")
 2781     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call/9")
 2782     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call/10")
 2783     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call/11")
 2784     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call/12")
 2785     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call/13")
 2786     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call/14")
 2787     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call/15")
 2788     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call/16")
 2789     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call/17")
 2790     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"  "F - test-convert-function-call/18")
 2791     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ebx"  "F - test-convert-function-call-with-literal-arg/6")
 2792     (check-next-stream-line-equal _test-output-stream "    bb/copy-to-ebx 3/imm32"  "F - test-convert-function-call/19")
 2793     (check-next-stream-line-equal _test-output-stream "    8b/-> %ebx 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/8")
 2794     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-call-with-literal-arg/27")
 2795     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-call-with-literal-arg/10")
 2796     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call/20")
 2797     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-call/21")
 2798     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call/22")
 2799     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call/23")
 2800     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call/24")
 2801     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call/25")
 2802     # . epilogue
 2803     89/<- %esp 5/r32/ebp
 2804     5d/pop-to-ebp
 2805     c3/return
 2806 
 2807 test-convert-function-call-with-inout-with-compound-type:
 2808     # . prologue
 2809     55/push-ebp
 2810     89/<- %ebp 4/r32/esp
 2811     # setup
 2812     (clear-stream _test-input-stream)
 2813     (clear-stream $_test-input-buffered-file->buffer)
 2814     (clear-stream _test-output-stream)
 2815     (clear-stream $_test-output-buffered-file->buffer)
 2816     #
 2817     (write _test-input-stream "fn f {\n")
 2818     (write _test-input-stream "  var x: (addr int)\n")
 2819     (write _test-input-stream "  g x\n")
 2820     (write _test-input-stream "}\n")
 2821     (write _test-input-stream "fn g a: (addr int) {\n")
 2822     (write _test-input-stream "}\n")
 2823     # convert
 2824     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 2825     (flush _test-output-buffered-file)
 2826 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2832     # check output
 2833     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-inout-with-compound-type/0")
 2834     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-inout-with-compound-type/1")
 2835     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-inout-with-compound-type/2")
 2836     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-inout-with-compound-type/3")
 2837     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-inout-with-compound-type/4")
 2838     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"     "F - test-convert-function-call-with-inout-with-compound-type/5")
 2839     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-call-with-inout-with-compound-type/6")
 2840     (check-next-stream-line-equal _test-output-stream "    (g *(ebp+0xfffffffc))"  "F - test-convert-function-call-with-inout-with-compound-type/7")
 2841     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-call-with-inout-with-compound-type/8")
 2842     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-inout-with-compound-type/9")
 2843     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"    "F - test-convert-function-call-with-inout-with-compound-type/10")
 2844     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-inout-with-compound-type/11")
 2845     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-inout-with-compound-type/12")
 2846     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-inout-with-compound-type/13")
 2847     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-inout-with-compound-type/14")
 2848     (check-next-stream-line-equal _test-output-stream "g:"                      "F - test-convert-function-call-with-inout-with-compound-type/15")
 2849     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-inout-with-compound-type/16")
 2850     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-inout-with-compound-type/17")
 2851     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-inout-with-compound-type/18")
 2852     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-inout-with-compound-type/19")
 2853     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-inout-with-compound-type/20")
 2854     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-inout-with-compound-type/21")
 2855     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-inout-with-compound-type/22")
 2856     # . epilogue
 2857     89/<- %esp 5/r32/ebp
 2858     5d/pop-to-ebp
 2859     c3/return
 2860 
 2861 test-convert-function-call-with-inout-with-type-parameter:
 2862     # . prologue
 2863     55/push-ebp
 2864     89/<- %ebp 4/r32/esp
 2865     # setup
 2866     (clear-stream _test-input-stream)
 2867     (clear-stream $_test-input-buffered-file->buffer)
 2868     (clear-stream _test-output-stream)
 2869     (clear-stream $_test-output-buffered-file->buffer)
 2870     (clear-stream _test-error-stream)
 2871     (clear-stream $_test-error-buffered-file->buffer)
 2872     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2873     68/push 0/imm32
 2874     68/push 0/imm32
 2875     89/<- %edx 4/r32/esp
 2876     (tailor-exit-descriptor %edx 0x10)
 2877     #
 2878     (write _test-input-stream "fn f {\n")
 2879     (write _test-input-stream "  var x: (addr int)\n")
 2880     (write _test-input-stream "  g x\n")
 2881     (write _test-input-stream "}\n")
 2882     (write _test-input-stream "fn g a: (addr _) {\n")
 2883     (write _test-input-stream "}\n")
 2884     # convert
 2885     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2886     # registers except esp clobbered at this point
 2887     # restore ed
 2888     89/<- %edx 4/r32/esp
 2889     (flush _test-output-buffered-file)
 2890     (flush _test-error-buffered-file)
 2891 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2897     # no error; types matched
 2898     (check-stream-equal _test-error-stream  ""  "F - test-convert-function-call-with-inout-with-type-parameter: error stream should be empty")
 2899     # don't bother checking the generated code; that's in the test 'test-local-clobbered-by-fn-output' below
 2900     # don't restore from ebp
 2901     81 0/subop/add %esp 8/imm32
 2902     # . epilogue
 2903     5d/pop-to-ebp
 2904     c3/return
 2905 
 2906 test-convert-function-call-with-incorrect-inout-type:
 2907     # . prologue
 2908     55/push-ebp
 2909     89/<- %ebp 4/r32/esp
 2910     # setup
 2911     (clear-stream _test-input-stream)
 2912     (clear-stream $_test-input-buffered-file->buffer)
 2913     (clear-stream _test-output-stream)
 2914     (clear-stream $_test-output-buffered-file->buffer)
 2915     (clear-stream _test-error-stream)
 2916     (clear-stream $_test-error-buffered-file->buffer)
 2917     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2918     68/push 0/imm32
 2919     68/push 0/imm32
 2920     89/<- %edx 4/r32/esp
 2921     (tailor-exit-descriptor %edx 0x10)
 2922     #
 2923     (write _test-input-stream "fn f {\n")
 2924     (write _test-input-stream "  var x: int\n")
 2925     (write _test-input-stream "  g x\n")
 2926     (write _test-input-stream "}\n")
 2927     (write _test-input-stream "fn g a: foo {\n")
 2928     (write _test-input-stream "}\n")
 2929     # convert
 2930     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2931     # registers except esp clobbered at this point
 2932     # restore ed
 2933     89/<- %edx 4/r32/esp
 2934     (flush _test-output-buffered-file)
 2935     (flush _test-error-buffered-file)
 2936 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2942     # check output
 2943     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-incorrect-inout-type: output should be empty")
 2944     (check-next-stream-line-equal _test-error-stream  "fn f: call g: type for inout 'x' is not right"  "F - test-convert-function-call-with-incorrect-inout-type: error message")
 2945     # check that stop(1) was called
 2946     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-incorrect-inout-type: exit status")
 2947     # don't restore from ebp
 2948     81 0/subop/add %esp 8/imm32
 2949     5d/pop-to-ebp
 2950     c3/return
 2951 
 2952 test-convert-function-call-with-inout-with-incorrect-compound-type:
 2953     # . prologue
 2954     55/push-ebp
 2955     89/<- %ebp 4/r32/esp
 2956     # setup
 2957     (clear-stream _test-input-stream)
 2958     (clear-stream $_test-input-buffered-file->buffer)
 2959     (clear-stream _test-output-stream)
 2960     (clear-stream $_test-output-buffered-file->buffer)
 2961     (clear-stream _test-error-stream)
 2962     (clear-stream $_test-error-buffered-file->buffer)
 2963     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 2964     68/push 0/imm32
 2965     68/push 0/imm32
 2966     89/<- %edx 4/r32/esp
 2967     (tailor-exit-descriptor %edx 0x10)
 2968     #
 2969     (write _test-input-stream "fn f {\n")
 2970     (write _test-input-stream "  var x: (addr int)\n")
 2971     (write _test-input-stream "  g x\n")
 2972     (write _test-input-stream "}\n")
 2973     (write _test-input-stream "fn g a: (addr bool) {\n")
 2974     (write _test-input-stream "}\n")
 2975     # convert
 2976     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 2977     # registers except esp clobbered at this point
 2978     # restore ed
 2979     89/<- %edx 4/r32/esp
 2980     (flush _test-output-buffered-file)
 2981     (flush _test-error-buffered-file)
 2982 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2988     # check output
 2989     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-inout-with-incorrect-compound-type: output should be empty")
 2990     (check-next-stream-line-equal _test-error-stream  "fn f: call g: type for inout 'x' is not right"  "F - test-convert-function-call-with-inout-with-incorrect-compound-type: error message")
 2991     # don't restore from ebp
 2992     81 0/subop/add %esp 8/imm32
 2993     # . epilogue
 2994     5d/pop-to-ebp
 2995     c3/return
 2996 
 2997 test-convert-function-call-with-inout-with-multiple-type-parameters:
 2998     # . prologue
 2999     55/push-ebp
 3000     89/<- %ebp 4/r32/esp
 3001     # setup
 3002     (clear-stream _test-input-stream)
 3003     (clear-stream $_test-input-buffered-file->buffer)
 3004     (clear-stream _test-output-stream)
 3005     (clear-stream $_test-output-buffered-file->buffer)
 3006     (clear-stream _test-error-stream)
 3007     (clear-stream $_test-error-buffered-file->buffer)
 3008     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3009     68/push 0/imm32
 3010     68/push 0/imm32
 3011     89/<- %edx 4/r32/esp
 3012     (tailor-exit-descriptor %edx 0x10)
 3013     #
 3014     (write _test-input-stream "fn f {\n")
 3015     (write _test-input-stream "  var x: (addr int)\n")
 3016     (write _test-input-stream "  var y: (addr int)\n")
 3017     (write _test-input-stream "  g x, y\n")
 3018     (write _test-input-stream "}\n")
 3019     (write _test-input-stream "fn g a: (addr _), b: (addr _) {\n")
 3020     (write _test-input-stream "}\n")
 3021     # convert
 3022     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3023     # registers except esp clobbered at this point
 3024     # restore ed
 3025     89/<- %edx 4/r32/esp
 3026     (flush _test-output-buffered-file)
 3027     (flush _test-error-buffered-file)
 3028 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3034     # no errors
 3035     (check-stream-equal _test-error-stream  ""  "F - test-convert-function-call-with-inout-with-multiple-type-parameters: error stream should be empty")
 3036     # don't bother checking the generated code
 3037     # don't restore from ebp
 3038     81 0/subop/add %esp 8/imm32
 3039     # . epilogue
 3040     5d/pop-to-ebp
 3041     c3/return
 3042 
 3043 test-type-parameter-matches-rest-of-type:
 3044     # . prologue
 3045     55/push-ebp
 3046     89/<- %ebp 4/r32/esp
 3047     # setup
 3048     (clear-stream _test-input-stream)
 3049     (clear-stream $_test-input-buffered-file->buffer)
 3050     (clear-stream _test-output-stream)
 3051     (clear-stream $_test-output-buffered-file->buffer)
 3052     (clear-stream _test-error-stream)
 3053     (clear-stream $_test-error-buffered-file->buffer)
 3054     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3055     68/push 0/imm32
 3056     68/push 0/imm32
 3057     89/<- %edx 4/r32/esp
 3058     (tailor-exit-descriptor %edx 0x10)
 3059     #
 3060     (write _test-input-stream "fn f {\n")
 3061     (write _test-input-stream "  var x: (addr array int)\n")
 3062     (write _test-input-stream "  g x\n")
 3063     (write _test-input-stream "}\n")
 3064     (write _test-input-stream "fn g a: (addr _) {\n")
 3065     (write _test-input-stream "}\n")
 3066     # convert
 3067     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3068     # registers except esp clobbered at this point
 3069     # restore ed
 3070     89/<- %edx 4/r32/esp
 3071     (flush _test-output-buffered-file)
 3072     (flush _test-error-buffered-file)
 3073 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3079     # no errors
 3080     (check-stream-equal _test-error-stream  ""  "F - test-type-parameter-matches-rest-of-type: error stream should be empty")
 3081     # don't bother checking the generated code
 3082     # don't restore from ebp
 3083     81 0/subop/add %esp 8/imm32
 3084     # . epilogue
 3085     5d/pop-to-ebp
 3086     c3/return
 3087 
 3088 test-convert-function-call-with-inout-with-incompatible-type-parameters:
 3089     # . prologue
 3090     55/push-ebp
 3091     89/<- %ebp 4/r32/esp
 3092     # setup
 3093     (clear-stream _test-input-stream)
 3094     (clear-stream $_test-input-buffered-file->buffer)
 3095     (clear-stream _test-output-stream)
 3096     (clear-stream $_test-output-buffered-file->buffer)
 3097     (clear-stream _test-error-stream)
 3098     (clear-stream $_test-error-buffered-file->buffer)
 3099     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3100     68/push 0/imm32
 3101     68/push 0/imm32
 3102     89/<- %edx 4/r32/esp
 3103     (tailor-exit-descriptor %edx 0x10)
 3104     #
 3105     (write _test-input-stream "fn f {\n")
 3106     (write _test-input-stream "  var x: (addr int)\n")
 3107     (write _test-input-stream "  var y: (addr boolean)\n")
 3108     (write _test-input-stream "  g x, y\n")
 3109     (write _test-input-stream "}\n")
 3110     (write _test-input-stream "fn g a: (addr _T), b: (addr _T) {\n")
 3111     (write _test-input-stream "}\n")
 3112     # convert
 3113     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3114     # registers except esp clobbered at this point
 3115     # restore ed
 3116     89/<- %edx 4/r32/esp
 3117     (flush _test-output-buffered-file)
 3118     (flush _test-error-buffered-file)
 3119 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3125     # check output
 3126     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-inout-with-incompatible-type-parameters: output should be empty")
 3127     (check-next-stream-line-equal _test-error-stream  "fn f: call g: type for inout 'y' is not right"  "F - test-convert-function-call-with-inout-with-incompatible-type-parameters: error message")
 3128     # don't restore from ebp
 3129     81 0/subop/add %esp 8/imm32
 3130     # . epilogue
 3131     5d/pop-to-ebp
 3132     c3/return
 3133 
 3134 test-convert-function-call-with-too-few-inouts:
 3135     # . prologue
 3136     55/push-ebp
 3137     89/<- %ebp 4/r32/esp
 3138     # setup
 3139     (clear-stream _test-input-stream)
 3140     (clear-stream $_test-input-buffered-file->buffer)
 3141     (clear-stream _test-output-stream)
 3142     (clear-stream $_test-output-buffered-file->buffer)
 3143     (clear-stream _test-error-stream)
 3144     (clear-stream $_test-error-buffered-file->buffer)
 3145     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3146     68/push 0/imm32
 3147     68/push 0/imm32
 3148     89/<- %edx 4/r32/esp
 3149     (tailor-exit-descriptor %edx 0x10)
 3150     #
 3151     (write _test-input-stream "fn f {\n")
 3152     (write _test-input-stream "  g\n")
 3153     (write _test-input-stream "}\n")
 3154     (write _test-input-stream "fn g a: int {\n")
 3155     (write _test-input-stream "}\n")
 3156     # convert
 3157     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3158     # registers except esp clobbered at this point
 3159     # restore ed
 3160     89/<- %edx 4/r32/esp
 3161     (flush _test-output-buffered-file)
 3162     (flush _test-error-buffered-file)
 3163 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3169     # check output
 3170     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-few-inouts: output should be empty")
 3171     (check-next-stream-line-equal _test-error-stream  "fn f: call g: too few inouts"  "F - test-convert-function-call-with-too-few-inouts: error message")
 3172     # check that stop(1) was called
 3173     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-few-inouts: exit status")
 3174     # don't restore from ebp
 3175     81 0/subop/add %esp 8/imm32
 3176     5d/pop-to-ebp
 3177     c3/return
 3178 
 3179 test-convert-function-call-with-too-many-inouts:
 3180     # . prologue
 3181     55/push-ebp
 3182     89/<- %ebp 4/r32/esp
 3183     # setup
 3184     (clear-stream _test-input-stream)
 3185     (clear-stream $_test-input-buffered-file->buffer)
 3186     (clear-stream _test-output-stream)
 3187     (clear-stream $_test-output-buffered-file->buffer)
 3188     (clear-stream _test-error-stream)
 3189     (clear-stream $_test-error-buffered-file->buffer)
 3190     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3191     68/push 0/imm32
 3192     68/push 0/imm32
 3193     89/<- %edx 4/r32/esp
 3194     (tailor-exit-descriptor %edx 0x10)
 3195     #
 3196     (write _test-input-stream "fn f {\n")
 3197     (write _test-input-stream "  var x: int\n")
 3198     (write _test-input-stream "  g x\n")
 3199     (write _test-input-stream "}\n")
 3200     (write _test-input-stream "fn g {\n")
 3201     (write _test-input-stream "}\n")
 3202     # convert
 3203     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3204     # registers except esp clobbered at this point
 3205     # restore ed
 3206     89/<- %edx 4/r32/esp
 3207     (flush _test-output-buffered-file)
 3208     (flush _test-error-buffered-file)
 3209 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3215     # check output
 3216     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-many-inouts: output should be empty")
 3217     (check-next-stream-line-equal _test-error-stream  "fn f: call g: too many inouts"  "F - test-convert-function-call-with-too-many-inouts: error message")
 3218     # check that stop(1) was called
 3219     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-many-inouts: exit status")
 3220     # don't restore from ebp
 3221     81 0/subop/add %esp 8/imm32
 3222     5d/pop-to-ebp
 3223     c3/return
 3224 
 3225 test-convert-function-call-with-incorrect-output-type:
 3226     # . prologue
 3227     55/push-ebp
 3228     89/<- %ebp 4/r32/esp
 3229     # setup
 3230     (clear-stream _test-input-stream)
 3231     (clear-stream $_test-input-buffered-file->buffer)
 3232     (clear-stream _test-output-stream)
 3233     (clear-stream $_test-output-buffered-file->buffer)
 3234     (clear-stream _test-error-stream)
 3235     (clear-stream $_test-error-buffered-file->buffer)
 3236     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3237     68/push 0/imm32
 3238     68/push 0/imm32
 3239     89/<- %edx 4/r32/esp
 3240     (tailor-exit-descriptor %edx 0x10)
 3241     #
 3242     (write _test-input-stream "fn f {\n")
 3243     (write _test-input-stream "  var x/eax: int <- g\n")
 3244     (write _test-input-stream "}\n")
 3245     (write _test-input-stream "fn g -> _/eax: foo {\n")
 3246     (write _test-input-stream "}\n")
 3247     # convert
 3248     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3249     # registers except esp clobbered at this point
 3250     # restore ed
 3251     89/<- %edx 4/r32/esp
 3252     (flush _test-output-buffered-file)
 3253     (flush _test-error-buffered-file)
 3254 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3260     # check output
 3261     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-incorrect-output-type: output should be empty")
 3262     (check-next-stream-line-equal _test-error-stream  "fn f: call g: type for output 'x' is not right"  "F - test-convert-function-call-with-incorrect-output-type: error message")
 3263     # check that stop(1) was called
 3264     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-incorrect-output-type: exit status")
 3265     # don't restore from ebp
 3266     81 0/subop/add %esp 8/imm32
 3267     5d/pop-to-ebp
 3268     c3/return
 3269 
 3270 test-convert-function-call-with-too-few-outputs:
 3271     # . prologue
 3272     55/push-ebp
 3273     89/<- %ebp 4/r32/esp
 3274     # setup
 3275     (clear-stream _test-input-stream)
 3276     (clear-stream $_test-input-buffered-file->buffer)
 3277     (clear-stream _test-output-stream)
 3278     (clear-stream $_test-output-buffered-file->buffer)
 3279     (clear-stream _test-error-stream)
 3280     (clear-stream $_test-error-buffered-file->buffer)
 3281     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3282     68/push 0/imm32
 3283     68/push 0/imm32
 3284     89/<- %edx 4/r32/esp
 3285     (tailor-exit-descriptor %edx 0x10)
 3286     #
 3287     (write _test-input-stream "fn f {\n")
 3288     (write _test-input-stream "  g\n")
 3289     (write _test-input-stream "}\n")
 3290     (write _test-input-stream "fn g -> _/eax: int {\n")
 3291     (write _test-input-stream "}\n")
 3292     # convert
 3293     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3294     # registers except esp clobbered at this point
 3295     # restore ed
 3296     89/<- %edx 4/r32/esp
 3297     (flush _test-output-buffered-file)
 3298     (flush _test-error-buffered-file)
 3299 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3305     # check output
 3306     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-few-outputs: output should be empty")
 3307     (check-next-stream-line-equal _test-error-stream  "fn f: call g: too few outputs"  "F - test-convert-function-call-with-too-few-outputs: error message")
 3308     # check that stop(1) was called
 3309     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-few-outputs: exit status")
 3310     # don't restore from ebp
 3311     81 0/subop/add %esp 8/imm32
 3312     5d/pop-to-ebp
 3313     c3/return
 3314 
 3315 test-convert-function-call-with-too-many-outputs:
 3316     # . prologue
 3317     55/push-ebp
 3318     89/<- %ebp 4/r32/esp
 3319     # setup
 3320     (clear-stream _test-input-stream)
 3321     (clear-stream $_test-input-buffered-file->buffer)
 3322     (clear-stream _test-output-stream)
 3323     (clear-stream $_test-output-buffered-file->buffer)
 3324     (clear-stream _test-error-stream)
 3325     (clear-stream $_test-error-buffered-file->buffer)
 3326     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3327     68/push 0/imm32
 3328     68/push 0/imm32
 3329     89/<- %edx 4/r32/esp
 3330     (tailor-exit-descriptor %edx 0x10)
 3331     #
 3332     (write _test-input-stream "fn f {\n")
 3333     (write _test-input-stream "  var x/eax: int <- g\n")
 3334     (write _test-input-stream "}\n")
 3335     (write _test-input-stream "fn g {\n")
 3336     (write _test-input-stream "}\n")
 3337     # convert
 3338     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3339     # registers except esp clobbered at this point
 3340     # restore ed
 3341     89/<- %edx 4/r32/esp
 3342     (flush _test-output-buffered-file)
 3343     (flush _test-error-buffered-file)
 3344 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3350     # check output
 3351     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-many-outputs: output should be empty")
 3352     (check-next-stream-line-equal _test-error-stream  "fn f: call g: too many outputs"  "F - test-convert-function-call-with-too-many-outputs: error message")
 3353     # check that stop(1) was called
 3354     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-many-outputs: exit status")
 3355     # don't restore from ebp
 3356     81 0/subop/add %esp 8/imm32
 3357     5d/pop-to-ebp
 3358     c3/return
 3359 
 3360 test-convert-function-call-with-missing-output-register:
 3361     # . prologue
 3362     55/push-ebp
 3363     89/<- %ebp 4/r32/esp
 3364     # setup
 3365     (clear-stream _test-input-stream)
 3366     (clear-stream $_test-input-buffered-file->buffer)
 3367     (clear-stream _test-output-stream)
 3368     (clear-stream $_test-output-buffered-file->buffer)
 3369     (clear-stream _test-error-stream)
 3370     (clear-stream $_test-error-buffered-file->buffer)
 3371     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3372     68/push 0/imm32
 3373     68/push 0/imm32
 3374     89/<- %edx 4/r32/esp
 3375     (tailor-exit-descriptor %edx 0x10)
 3376     #
 3377     (write _test-input-stream "fn f {\n")
 3378     (write _test-input-stream "  var x: int\n")
 3379     (write _test-input-stream "  x <- g\n")
 3380     (write _test-input-stream "}\n")
 3381     (write _test-input-stream "fn g -> _/eax: int {\n")
 3382     (write _test-input-stream "}\n")
 3383     # convert
 3384     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3385     # registers except esp clobbered at this point
 3386     # restore ed
 3387     89/<- %edx 4/r32/esp
 3388     (flush _test-output-buffered-file)
 3389     (flush _test-error-buffered-file)
 3390 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3396     # check output
 3397     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-missing-output-register: output should be empty")
 3398     (check-next-stream-line-equal _test-error-stream  "fn f: call g: output 'x' is not in a register"  "F - test-convert-function-call-with-missing-output-register: error message")
 3399     # check that stop(1) was called
 3400     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-missing-output-register: exit status")
 3401     # don't restore from ebp
 3402     81 0/subop/add %esp 8/imm32
 3403     5d/pop-to-ebp
 3404     c3/return
 3405 
 3406 test-convert-function-call-with-incorrect-output-register:
 3407     # . prologue
 3408     55/push-ebp
 3409     89/<- %ebp 4/r32/esp
 3410     # setup
 3411     (clear-stream _test-input-stream)
 3412     (clear-stream $_test-input-buffered-file->buffer)
 3413     (clear-stream _test-output-stream)
 3414     (clear-stream $_test-output-buffered-file->buffer)
 3415     (clear-stream _test-error-stream)
 3416     (clear-stream $_test-error-buffered-file->buffer)
 3417     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3418     68/push 0/imm32
 3419     68/push 0/imm32
 3420     89/<- %edx 4/r32/esp
 3421     (tailor-exit-descriptor %edx 0x10)
 3422     #
 3423     (write _test-input-stream "fn f {\n")
 3424     (write _test-input-stream "  var x/ecx: int <- g\n")
 3425     (write _test-input-stream "}\n")
 3426     (write _test-input-stream "fn g -> _/eax: int {\n")
 3427     (write _test-input-stream "}\n")
 3428     # convert
 3429     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3430     # registers except esp clobbered at this point
 3431     # restore ed
 3432     89/<- %edx 4/r32/esp
 3433     (flush _test-output-buffered-file)
 3434     (flush _test-error-buffered-file)
 3435 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3441     # check output
 3442     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-incorrect-output-register: output should be empty")
 3443     (check-next-stream-line-equal _test-error-stream  "fn f: call g: register for output 'x' is not right"  "F - test-convert-function-call-with-incorrect-output-register: error message")
 3444     # check that stop(1) was called
 3445     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-incorrect-output-register: exit status")
 3446     # don't restore from ebp
 3447     81 0/subop/add %esp 8/imm32
 3448     5d/pop-to-ebp
 3449     c3/return
 3450 
 3451 test-convert-function-with-local-var-dereferenced:
 3452     # . prologue
 3453     55/push-ebp
 3454     89/<- %ebp 4/r32/esp
 3455     # setup
 3456     (clear-stream _test-input-stream)
 3457     (clear-stream $_test-input-buffered-file->buffer)
 3458     (clear-stream _test-output-stream)
 3459     (clear-stream $_test-output-buffered-file->buffer)
 3460     #
 3461     (write _test-input-stream "fn foo {\n")
 3462     (write _test-input-stream "  var x/ecx: (addr int) <- copy 0\n")
 3463     (write _test-input-stream "  increment *x\n")
 3464     (write _test-input-stream "}\n")
 3465     # convert
 3466     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3467     (flush _test-output-buffered-file)
 3468 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3474     # check output
 3475     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-dereferenced/0")
 3476     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-dereferenced/1")
 3477     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-dereferenced/2")
 3478     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-dereferenced/3")
 3479     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-dereferenced/4")
 3480     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-dereferenced/5")
 3481     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-local-var-dereferenced/6")
 3482     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-function-with-local-var-dereferenced/7")
 3483     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *ecx"  "F - test-convert-function-with-local-var-dereferenced/8")
 3484     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-local-var-dereferenced/9")
 3485     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-dereferenced/10")
 3486     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-dereferenced/11")
 3487     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-dereferenced/12")
 3488     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-dereferenced/13")
 3489     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-dereferenced/14")
 3490     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-dereferenced/15")
 3491     # . epilogue
 3492     89/<- %esp 5/r32/ebp
 3493     5d/pop-to-ebp
 3494     c3/return
 3495 
 3496 test-dereference-of-var-on-stack:
 3497     # . prologue
 3498     55/push-ebp
 3499     89/<- %ebp 4/r32/esp
 3500     # setup
 3501     (clear-stream _test-input-stream)
 3502     (clear-stream $_test-input-buffered-file->buffer)
 3503     (clear-stream _test-output-stream)
 3504     (clear-stream $_test-output-buffered-file->buffer)
 3505     (clear-stream _test-error-stream)
 3506     (clear-stream $_test-error-buffered-file->buffer)
 3507     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3508     68/push 0/imm32
 3509     68/push 0/imm32
 3510     89/<- %edx 4/r32/esp
 3511     (tailor-exit-descriptor %edx 0x10)
 3512     #
 3513     (write _test-input-stream "fn foo {\n")
 3514     (write _test-input-stream "  var x: (addr int)\n")
 3515     (write _test-input-stream "  increment *x\n")
 3516     (write _test-input-stream "}\n")
 3517     # convert
 3518     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3519     # registers except esp clobbered at this point
 3520     # restore ed
 3521     89/<- %edx 4/r32/esp
 3522     (flush _test-output-buffered-file)
 3523     (flush _test-error-buffered-file)
 3524 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3530     # check output
 3531     (check-stream-equal _test-output-stream  ""  "F - test-dereference-of-var-on-stack: output should be empty")
 3532     (check-next-stream-line-equal _test-error-stream  "fn foo: cannot dereference var 'x' on stack"  "F - test-dereference-of-var-on-stack: error message")
 3533     # check that stop(1) was called
 3534     (check-ints-equal *(edx+4) 2 "F - test-dereference-of-var-on-stack: exit status")
 3535     # don't restore from ebp
 3536     81 0/subop/add %esp 8/imm32
 3537     # . epilogue
 3538     5d/pop-to-ebp
 3539     c3/return
 3540 
 3541 test-convert-function-with-byte-operations:
 3542     # . prologue
 3543     55/push-ebp
 3544     89/<- %ebp 4/r32/esp
 3545     # setup
 3546     (clear-stream _test-input-stream)
 3547     (clear-stream $_test-input-buffered-file->buffer)
 3548     (clear-stream _test-output-stream)
 3549     (clear-stream $_test-output-buffered-file->buffer)
 3550     #
 3551     (write _test-input-stream "fn foo {\n")
 3552     (write _test-input-stream "  var x/eax: byte <- copy 0\n")
 3553     (write _test-input-stream "  var y/ecx: byte <- copy 0\n")
 3554     (write _test-input-stream "  y <- copy-byte x\n")
 3555     (write _test-input-stream "  var z/edx: (addr byte) <- copy 0\n")
 3556     (write _test-input-stream "  y <- copy-byte *z\n")
 3557     (write _test-input-stream "  copy-byte-to *z, x\n")
 3558     (write _test-input-stream "}\n")
 3559     # convert
 3560     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3561     (flush _test-output-buffered-file)
 3562 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3568     # check output
 3569     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-function-with-byte-operations/0")
 3570     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-function-with-byte-operations/1")
 3571     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-function-with-byte-operations/2")
 3572     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-function-with-byte-operations/3")
 3573     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-function-with-byte-operations/4")
 3574     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-function-with-byte-operations/5")
 3575     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-function-with-byte-operations/6")
 3576     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-function-with-byte-operations/7")
 3577     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-function-with-byte-operations/8")
 3578     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"                  "F - test-convert-function-with-byte-operations/9")
 3579     (check-next-stream-line-equal _test-output-stream "    8a/byte-> %eax 0x00000001/r32"           "F - test-convert-function-with-byte-operations/10")
 3580     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %edx"                    "F - test-convert-function-with-byte-operations/11")
 3581     (check-next-stream-line-equal _test-output-stream "    ba/copy-to-edx 0/imm32"                  "F - test-convert-function-with-byte-operations/12")
 3582     (check-next-stream-line-equal _test-output-stream "    8a/byte-> *edx 0x00000001/r32"           "F - test-convert-function-with-byte-operations/13")
 3583     (check-next-stream-line-equal _test-output-stream "    88/byte<- *edx 0x00000000/r32"           "F - test-convert-function-with-byte-operations/14")
 3584     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %edx"                     "F - test-convert-function-with-byte-operations/15")
 3585     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-function-with-byte-operations/16")
 3586     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-function-with-byte-operations/17")
 3587     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-function-with-byte-operations/18")
 3588     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-function-with-byte-operations/19")
 3589     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-function-with-byte-operations/20")
 3590     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-function-with-byte-operations/21")
 3591     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-function-with-byte-operations/22")
 3592     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-function-with-byte-operations/23")
 3593     # . epilogue
 3594     89/<- %esp 5/r32/ebp
 3595     5d/pop-to-ebp
 3596     c3/return
 3597 
 3598 # variables of type 'byte' are not allowed on the stack
 3599 test-byte-values-on-stack:
 3600     # . prologue
 3601     55/push-ebp
 3602     89/<- %ebp 4/r32/esp
 3603     # setup
 3604     (clear-stream _test-input-stream)
 3605     (clear-stream $_test-input-buffered-file->buffer)
 3606     (clear-stream _test-output-stream)
 3607     (clear-stream $_test-output-buffered-file->buffer)
 3608     (clear-stream _test-error-stream)
 3609     (clear-stream $_test-error-buffered-file->buffer)
 3610     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3611     68/push 0/imm32
 3612     68/push 0/imm32
 3613     89/<- %edx 4/r32/esp
 3614     (tailor-exit-descriptor %edx 0x10)
 3615     #
 3616     (write _test-input-stream "fn foo {\n")
 3617     (write _test-input-stream "  var x: byte\n")
 3618     (write _test-input-stream "}\n")
 3619     # convert
 3620     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3621     # registers except esp clobbered at this point
 3622     # restore ed
 3623     89/<- %edx 4/r32/esp
 3624     (flush _test-output-buffered-file)
 3625     (flush _test-error-buffered-file)
 3626 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3632     # check output
 3633     (check-stream-equal _test-output-stream  ""  "F - test-byte-values-on-stack: output should be empty")
 3634     (check-next-stream-line-equal _test-error-stream  "fn foo: var 'x' of type 'byte' cannot be on the stack"  "F - test-byte-values-on-stack: error message")
 3635     # check that stop(1) was called
 3636     (check-ints-equal *(edx+4) 2 "F - test-byte-values-on-stack: exit status")
 3637     # don't restore from ebp
 3638     81 0/subop/add %esp 8/imm32
 3639     # . epilogue
 3640     5d/pop-to-ebp
 3641     c3/return
 3642 
 3643 # variables of type 'byte' are not allowed in esi or edi
 3644 test-byte-values-in-unsupported-registers:
 3645     # . prologue
 3646     55/push-ebp
 3647     89/<- %ebp 4/r32/esp
 3648     # setup
 3649     (clear-stream _test-input-stream)
 3650     (clear-stream $_test-input-buffered-file->buffer)
 3651     (clear-stream _test-output-stream)
 3652     (clear-stream $_test-output-buffered-file->buffer)
 3653     (clear-stream _test-error-stream)
 3654     (clear-stream $_test-error-buffered-file->buffer)
 3655     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3656     68/push 0/imm32
 3657     68/push 0/imm32
 3658     89/<- %edx 4/r32/esp
 3659     (tailor-exit-descriptor %edx 0x10)
 3660     #
 3661     (write _test-input-stream "fn foo {\n")
 3662     (write _test-input-stream "  var x/esi: byte <- copy 0\n")
 3663     (write _test-input-stream "}\n")
 3664     # convert
 3665     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3666     # registers except esp clobbered at this point
 3667     # restore ed
 3668     89/<- %edx 4/r32/esp
 3669     (flush _test-output-buffered-file)
 3670     (flush _test-error-buffered-file)
 3671 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3677     # check output
 3678     (check-stream-equal _test-output-stream  ""  "F - test-byte-values-in-unsupported-registers: output should be empty")
 3679     (check-next-stream-line-equal _test-error-stream  "fn foo: var 'x' of type 'byte' cannot be in esi or edi"  "F - test-byte-values-in-unsupported-registers: error message")
 3680     # check that stop(1) was called
 3681     (check-ints-equal *(edx+4) 2 "F - test-byte-values-in-unsupported-registers: exit status")
 3682     # don't restore from ebp
 3683     81 0/subop/add %esp 8/imm32
 3684     # . epilogue
 3685     5d/pop-to-ebp
 3686     c3/return
 3687 
 3688 # variables of type 'byte' _can_ be function args. They then occupy 4 bytes.
 3689 test-copy-byte-var-from-fn-arg:
 3690     # . prologue
 3691     55/push-ebp
 3692     89/<- %ebp 4/r32/esp
 3693     # setup
 3694     (clear-stream _test-input-stream)
 3695     (clear-stream $_test-input-buffered-file->buffer)
 3696     (clear-stream _test-output-stream)
 3697     (clear-stream $_test-output-buffered-file->buffer)
 3698     #
 3699     (write _test-input-stream "fn foo x: byte, y: int {\n")
 3700     (write _test-input-stream "  var a/eax: byte <- copy x\n")
 3701     (write _test-input-stream "  var b/eax: int <- copy y\n")
 3702     (write _test-input-stream "}\n")
 3703     # convert
 3704     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3705     (flush _test-output-buffered-file)
 3706 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3712     # check output
 3713     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-copy-byte-from-fn-arg/0")
 3714     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-copy-byte-from-fn-arg/1")
 3715     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-copy-byte-from-fn-arg/2")
 3716     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-copy-byte-from-fn-arg/3")
 3717     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-copy-byte-from-fn-arg/4")
 3718     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-copy-byte-from-fn-arg/5")
 3719     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-copy-byte-from-fn-arg/6")
 3720     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-copy-byte-from-fn-arg/7")
 3721     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x0000000c) 0x00000000/r32"  "F - test-copy-byte-from-fn-arg/8")
 3722     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"   "F - test-copy-byte-from-fn-arg/9")
 3723     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-copy-byte-from-fn-arg/10")
 3724     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-copy-byte-from-fn-arg/11")
 3725     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-copy-byte-from-fn-arg/12")
 3726     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-copy-byte-from-fn-arg/13")
 3727     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-copy-byte-from-fn-arg/14")
 3728     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-copy-byte-from-fn-arg/15")
 3729     # . epilogue
 3730     89/<- %esp 5/r32/ebp
 3731     5d/pop-to-ebp
 3732     c3/return
 3733 
 3734 test-convert-compare-register-with-literal:
 3735     # . prologue
 3736     55/push-ebp
 3737     89/<- %ebp 4/r32/esp
 3738     # setup
 3739     (clear-stream _test-input-stream)
 3740     (clear-stream $_test-input-buffered-file->buffer)
 3741     (clear-stream _test-output-stream)
 3742     (clear-stream $_test-output-buffered-file->buffer)
 3743     #
 3744     (write _test-input-stream "fn foo {\n")
 3745     (write _test-input-stream "  var x/ecx: int <- copy 0\n")
 3746     (write _test-input-stream "  compare x, 0\n")
 3747     (write _test-input-stream "}\n")
 3748     # convert
 3749     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3750     (flush _test-output-buffered-file)
 3751 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3757     # check output
 3758     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-compare-register-with-literal/0")
 3759     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-compare-register-with-literal/1")
 3760     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-compare-register-with-literal/2")
 3761     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-compare-register-with-literal/3")
 3762     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-compare-register-with-literal/4")
 3763     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-compare-register-with-literal/5")
 3764     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-compare-register-with-literal/6")
 3765     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-compare-register-with-literal/7")
 3766     (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %ecx 0/imm32"  "F - test-convert-compare-register-with-literal/8")
 3767     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-compare-register-with-literal/9")
 3768     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-compare-register-with-literal/10")
 3769     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-compare-register-with-literal/11")
 3770     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-compare-register-with-literal/12")
 3771     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-compare-register-with-literal/13")
 3772     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-compare-register-with-literal/14")
 3773     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-compare-register-with-literal/15")
 3774     # . epilogue
 3775     89/<- %esp 5/r32/ebp
 3776     5d/pop-to-ebp
 3777     c3/return
 3778 
 3779 test-unknown-variable:
 3780     # . prologue
 3781     55/push-ebp
 3782     89/<- %ebp 4/r32/esp
 3783     # setup
 3784     (clear-stream _test-input-stream)
 3785     (clear-stream $_test-input-buffered-file->buffer)
 3786     (clear-stream _test-output-stream)
 3787     (clear-stream $_test-output-buffered-file->buffer)
 3788     (clear-stream _test-error-stream)
 3789     (clear-stream $_test-error-buffered-file->buffer)
 3790     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3791     68/push 0/imm32
 3792     68/push 0/imm32
 3793     89/<- %edx 4/r32/esp
 3794     (tailor-exit-descriptor %edx 0x10)
 3795     #
 3796     (write _test-input-stream "fn foo {\n")
 3797     (write _test-input-stream "  compare x, 0\n")
 3798     (write _test-input-stream "}\n")
 3799     # convert
 3800     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 3801     # registers except esp clobbered at this point
 3802     # restore ed
 3803     89/<- %edx 4/r32/esp
 3804     (flush _test-output-buffered-file)
 3805     (flush _test-error-buffered-file)
 3806 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3812     # check output
 3813     (check-stream-equal _test-output-stream  ""  "F - test-unknown-variable: output should be empty")
 3814     (check-next-stream-line-equal _test-error-stream  "fn foo: unknown variable 'x'"  "F - test-unknown-variable: error message")
 3815     # check that stop(1) was called
 3816     (check-ints-equal *(edx+4) 2 "F - test-unknown-variable: exit status")
 3817     # don't restore from ebp
 3818     81 0/subop/add %esp 8/imm32
 3819     # . epilogue
 3820     5d/pop-to-ebp
 3821     c3/return
 3822 
 3823 test-convert-function-with-local-var-in-block:
 3824     # . prologue
 3825     55/push-ebp
 3826     89/<- %ebp 4/r32/esp
 3827     # setup
 3828     (clear-stream _test-input-stream)
 3829     (clear-stream $_test-input-buffered-file->buffer)
 3830     (clear-stream _test-output-stream)
 3831     (clear-stream $_test-output-buffered-file->buffer)
 3832     #
 3833     (write _test-input-stream "fn foo {\n")
 3834     (write _test-input-stream "  {\n")
 3835     (write _test-input-stream "    var x: int\n")
 3836     (write _test-input-stream "    increment x\n")
 3837     (write _test-input-stream "  }\n")
 3838     (write _test-input-stream "}\n")
 3839     # convert
 3840     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3841     (flush _test-output-buffered-file)
 3842 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3848     # check output
 3849     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-block/0")
 3850     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-block/1")
 3851     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-block/2")
 3852     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-block/3")
 3853     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-block/4")
 3854     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-block/5")
 3855     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-local-var-in-block/6")
 3856     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-local-var-in-block/7")
 3857     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-local-var-in-block/8")
 3858     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-local-var-in-block/9")
 3859     (check-next-stream-line-equal _test-output-stream "      81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-local-var-in-block/10")
 3860     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-local-var-in-block/11")
 3861     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-local-var-in-block/12")
 3862     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-block/13")
 3863     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-block/14")
 3864     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-block/15")
 3865     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-block/16")
 3866     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-block/17")
 3867     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-block/18")
 3868     # . epilogue
 3869     89/<- %esp 5/r32/ebp
 3870     5d/pop-to-ebp
 3871     c3/return
 3872 
 3873 test-convert-function-with-local-var-in-mem-after-block:
 3874     # . prologue
 3875     55/push-ebp
 3876     89/<- %ebp 4/r32/esp
 3877     # setup
 3878     (clear-stream _test-input-stream)
 3879     (clear-stream $_test-input-buffered-file->buffer)
 3880     (clear-stream _test-output-stream)
 3881     (clear-stream $_test-output-buffered-file->buffer)
 3882     #
 3883     (write _test-input-stream "fn foo {\n")
 3884     (write _test-input-stream "  {\n")
 3885     (write _test-input-stream "    var y: int\n")
 3886     (write _test-input-stream "  }\n")
 3887     (write _test-input-stream "  var x: int\n")
 3888     (write _test-input-stream "  increment x\n")
 3889     (write _test-input-stream "}\n")
 3890     # convert
 3891     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3892     (flush _test-output-buffered-file)
 3893 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3899     # check output
 3900     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-mem-after-block/0")
 3901     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-mem-after-block/1")
 3902     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-mem-after-block/2")
 3903     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-mem-after-block/3")
 3904     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-mem-after-block/4")
 3905     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-mem-after-block/5")
 3906     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-local-var-in-mem-after-block/6")
 3907     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-local-var-in-mem-after-block/7")
 3908     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-local-var-in-mem-after-block/8")
 3909     (check-next-stream-line-equal _test-output-stream "      81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-local-var-in-mem-after-block/9")
 3910     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-local-var-in-mem-after-block/10")
 3911     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-local-var-in-mem-after-block/11")
 3912     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-in-mem-after-block/12")
 3913     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-local-var-in-mem-after-block/13")
 3914     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-local-var-in-mem-after-block/14")
 3915     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-mem-after-block/15")
 3916     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-mem-after-block/16")
 3917     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-mem-after-block/17")
 3918     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-mem-after-block/18")
 3919     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-mem-after-block/19")
 3920     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-mem-after-block/20")
 3921     # . epilogue
 3922     89/<- %esp 5/r32/ebp
 3923     5d/pop-to-ebp
 3924     c3/return
 3925 
 3926 test-convert-function-with-local-var-in-named-block:
 3927     # . prologue
 3928     55/push-ebp
 3929     89/<- %ebp 4/r32/esp
 3930     # setup
 3931     (clear-stream _test-input-stream)
 3932     (clear-stream $_test-input-buffered-file->buffer)
 3933     (clear-stream _test-output-stream)
 3934     (clear-stream $_test-output-buffered-file->buffer)
 3935     #
 3936     (write _test-input-stream "fn foo {\n")
 3937     (write _test-input-stream "  $bar: {\n")
 3938     (write _test-input-stream "    var x: int\n")
 3939     (write _test-input-stream "    increment x\n")
 3940     (write _test-input-stream "  }\n")
 3941     (write _test-input-stream "}\n")
 3942     # convert
 3943     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 3944     (flush _test-output-buffered-file)
 3945 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 3951     # check output
 3952     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-named-block/0")
 3953     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-named-block/1")
 3954     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-named-block/2")
 3955     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-named-block/3")
 3956     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-named-block/4")
 3957     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-named-block/5")
 3958     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-local-var-in-named-block/6")
 3959     (check-next-stream-line-equal _test-output-stream "$bar:loop:"              "F - test-convert-function-with-local-var-in-named-block/7")
 3960     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-local-var-in-named-block/8")
 3961     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-local-var-in-named-block/9")
 3962     (check-next-stream-line-equal _test-output-stream "      81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-local-var-in-named-block/10")
 3963     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-local-var-in-named-block/11")
 3964     (check-next-stream-line-equal _test-output-stream "$bar:break:"             "F - test-convert-function-with-local-var-in-named-block/12")
 3965     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-named-block/13")
 3966     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-named-block/14")
 3967     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-named-block/15")
 3968     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-named-block/16")
 3969     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-named-block/17")
 3970     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-named-block/18")
 3971     # . epilogue
 3972     89/<- %esp 5/r32/ebp
 3973     5d/pop-to-ebp
 3974     c3/return
 3975 
 3976 test-unknown-variable-in-named-block:
 3977     # . prologue
 3978     55/push-ebp
 3979     89/<- %ebp 4/r32/esp
 3980     # setup
 3981     (clear-stream _test-input-stream)
 3982     (clear-stream $_test-input-buffered-file->buffer)
 3983     (clear-stream _test-output-stream)
 3984     (clear-stream $_test-output-buffered-file->buffer)
 3985     (clear-stream _test-error-stream)
 3986     (clear-stream $_test-error-buffered-file->buffer)
 3987     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 3988     68/push 0/imm32
 3989     68/push 0/imm32
 3990     89/<- %edx 4/r32/esp
 3991     (tailor-exit-descriptor %edx 0x10)
 3992     #
 3993     (write _test-input-stream "fn foo {\n")
 3994     (write _test-input-stream "  $a: {\n")
 3995     (write _test-input-stream "    compare x, 0\n")
 3996     (write _test-input-stream "  }\n")
 3997     (write _test-input-stream "}\n")
 3998     # convert
 3999     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 4000     # registers except esp clobbered at this point
 4001     # restore ed
 4002     89/<- %edx 4/r32/esp
 4003     (flush _test-output-buffered-file)
 4004     (flush _test-error-buffered-file)
 4005 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4011     # check output
 4012     (check-stream-equal _test-output-stream  ""  "F - test-unknown-variable-in-named-block: output should be empty")
 4013     (check-next-stream-line-equal _test-error-stream  "fn foo: unknown variable 'x'"  "F - test-unknown-variable-in-named-block: error message")
 4014     # check that stop(1) was called
 4015     (check-ints-equal *(edx+4) 2 "F - test-unknown-variable-in-named-block: exit status")
 4016     # don't restore from ebp
 4017     81 0/subop/add %esp 8/imm32
 4018     # . epilogue
 4019     5d/pop-to-ebp
 4020     c3/return
 4021 
 4022 test-always-shadow-outermost-reg-vars-in-function:
 4023     # . prologue
 4024     55/push-ebp
 4025     89/<- %ebp 4/r32/esp
 4026     # setup
 4027     (clear-stream _test-input-stream)
 4028     (clear-stream $_test-input-buffered-file->buffer)
 4029     (clear-stream _test-output-stream)
 4030     (clear-stream $_test-output-buffered-file->buffer)
 4031     #
 4032     (write _test-input-stream "fn foo {\n")
 4033     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 4034     (write _test-input-stream "}\n")
 4035     # convert
 4036     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4037     (flush _test-output-buffered-file)
 4038 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4044     # check output
 4045     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-always-shadow-outermost-reg-vars-in-function/0")
 4046     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-always-shadow-outermost-reg-vars-in-function/1")
 4047     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-always-shadow-outermost-reg-vars-in-function/2")
 4048     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-always-shadow-outermost-reg-vars-in-function/3")
 4049     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-always-shadow-outermost-reg-vars-in-function/4")
 4050     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-always-shadow-outermost-reg-vars-in-function/5")
 4051     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-compare-register-with-literal/6")
 4052     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-always-shadow-outermost-reg-vars-in-function/8")
 4053     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-compare-register-with-literal/9")
 4054     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-always-shadow-outermost-reg-vars-in-function/12")
 4055     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-always-shadow-outermost-reg-vars-in-function/13")
 4056     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-always-shadow-outermost-reg-vars-in-function/14")
 4057     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-always-shadow-outermost-reg-vars-in-function/15")
 4058     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-always-shadow-outermost-reg-vars-in-function/16")
 4059     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-always-shadow-outermost-reg-vars-in-function/17")
 4060     # . epilogue
 4061     89/<- %esp 5/r32/ebp
 4062     5d/pop-to-ebp
 4063     c3/return
 4064 
 4065 test-shadow-local:
 4066     # . prologue
 4067     55/push-ebp
 4068     89/<- %ebp 4/r32/esp
 4069     # setup
 4070     (clear-stream _test-input-stream)
 4071     (clear-stream $_test-input-buffered-file->buffer)
 4072     (clear-stream _test-output-stream)
 4073     (clear-stream $_test-output-buffered-file->buffer)
 4074     #
 4075     (write _test-input-stream "fn foo {\n")
 4076     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 4077     (write _test-input-stream "  {\n")
 4078     (write _test-input-stream "    var y/ecx: int <- copy 4\n")
 4079     (write _test-input-stream "  }\n")
 4080     (write _test-input-stream "  x <- increment\n")
 4081     (write _test-input-stream "}\n")
 4082     # convert
 4083     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4084     (flush _test-output-buffered-file)
 4085 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4091     # check output
 4092     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-shadow-local/0")
 4093     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-shadow-local/1")
 4094     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-shadow-local/2")
 4095     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-shadow-local/3")
 4096     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-shadow-local/4")
 4097     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-shadow-local/5")
 4098     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-shadow-local/6")
 4099     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-shadow-local/7")
 4100     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-shadow-local/8")
 4101     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-shadow-local/9")
 4102     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %ecx"  "F - test-shadow-local/10")
 4103     (check-next-stream-line-equal _test-output-stream "      b9/copy-to-ecx 4/imm32"  "F - test-shadow-local/11")
 4104     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %ecx" "F - test-shadow-local/12")
 4105     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-shadow-local/13")
 4106     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-shadow-local/14")
 4107     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-shadow-local/15")
 4108     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-shadow-local/16")
 4109     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-shadow-local/17")
 4110     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-shadow-local/18")
 4111     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-shadow-local/19")
 4112     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-shadow-local/20")
 4113     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-shadow-local/21")
 4114     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-shadow-local/22")
 4115     # . epilogue
 4116     89/<- %esp 5/r32/ebp
 4117     5d/pop-to-ebp
 4118     c3/return
 4119 
 4120 test-shadow-name:
 4121     # . prologue
 4122     55/push-ebp
 4123     89/<- %ebp 4/r32/esp
 4124     # setup
 4125     (clear-stream _test-input-stream)
 4126     (clear-stream $_test-input-buffered-file->buffer)
 4127     (clear-stream _test-output-stream)
 4128     (clear-stream $_test-output-buffered-file->buffer)
 4129     #
 4130     (write _test-input-stream "fn foo {\n")
 4131     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 4132     (write _test-input-stream "  {\n")
 4133     (write _test-input-stream "    var x/edx: int <- copy 4\n")
 4134     (write _test-input-stream "  }\n")
 4135     (write _test-input-stream "  x <- increment\n")
 4136     (write _test-input-stream "}\n")
 4137     # convert
 4138     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4139     (flush _test-output-buffered-file)
 4140 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4146     # check output
 4147     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-shadow-name/0")
 4148     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-shadow-name/1")
 4149     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-shadow-name/2")
 4150     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-shadow-name/3")
 4151     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-shadow-name/4")
 4152     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-shadow-name/5")
 4153     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-shadow-name/6")
 4154     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-shadow-name/7")
 4155     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-shadow-name/8")
 4156     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-shadow-name/9")
 4157     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %edx"  "F - test-shadow-name/10")
 4158     (check-next-stream-line-equal _test-output-stream "      ba/copy-to-edx 4/imm32"  "F - test-shadow-name/11")
 4159     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %edx" "F - test-shadow-name/12")
 4160     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-shadow-name/13")
 4161     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-shadow-name/14")
 4162     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-shadow-name/15")
 4163     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-shadow-name/16")
 4164     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-shadow-name/17")
 4165     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-shadow-name/18")
 4166     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-shadow-name/19")
 4167     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-shadow-name/20")
 4168     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-shadow-name/21")
 4169     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-shadow-name/22")
 4170     # . epilogue
 4171     89/<- %esp 5/r32/ebp
 4172     5d/pop-to-ebp
 4173     c3/return
 4174 
 4175 test-shadow-name-2:
 4176     # . prologue
 4177     55/push-ebp
 4178     89/<- %ebp 4/r32/esp
 4179     # setup
 4180     (clear-stream _test-input-stream)
 4181     (clear-stream $_test-input-buffered-file->buffer)
 4182     (clear-stream _test-output-stream)
 4183     (clear-stream $_test-output-buffered-file->buffer)
 4184     #
 4185     (write _test-input-stream "fn foo {\n")
 4186     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 4187     (write _test-input-stream "  {\n")
 4188     (write _test-input-stream "    var x/edx: int <- copy 4\n")
 4189     (write _test-input-stream "    var y/ecx: int <- copy 5\n")
 4190     (write _test-input-stream "  }\n")
 4191     (write _test-input-stream "  x <- increment\n")
 4192     (write _test-input-stream "}\n")
 4193     # convert
 4194     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4195     (flush _test-output-buffered-file)
 4196 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4202     # check output
 4203     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-shadow-name-2/0")
 4204     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-shadow-name-2/1")
 4205     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-shadow-name-2/2")
 4206     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-shadow-name-2/3")
 4207     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-shadow-name-2/4")
 4208     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-shadow-name-2/5")
 4209     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-shadow-name-2/6")
 4210     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-shadow-name-2/7")
 4211     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-shadow-name-2/8")
 4212     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-shadow-name-2/9")
 4213     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %edx"  "F - test-shadow-name-2/10")
 4214     (check-next-stream-line-equal _test-output-stream "      ba/copy-to-edx 4/imm32"  "F - test-shadow-name-2/11")
 4215     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %ecx"  "F - test-shadow-name-2/12")
 4216     (check-next-stream-line-equal _test-output-stream "      b9/copy-to-ecx 5/imm32"  "F - test-shadow-name-2/13")
 4217     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %ecx" "F - test-shadow-name-2/14")
 4218     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %edx" "F - test-shadow-name-2/15")
 4219     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-shadow-name-2/16")
 4220     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-shadow-name-2/17")
 4221     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-shadow-name-2/18")
 4222     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-shadow-name-2/19")
 4223     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-shadow-name-2/20")
 4224     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-shadow-name-2/21")
 4225     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-shadow-name-2/22")
 4226     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-shadow-name-2/23")
 4227     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-shadow-name-2/24")
 4228     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-shadow-name-2/25")
 4229     # . epilogue
 4230     89/<- %esp 5/r32/ebp
 4231     5d/pop-to-ebp
 4232     c3/return
 4233 
 4234 test-do-not-spill-same-register-in-block:
 4235     # . prologue
 4236     55/push-ebp
 4237     89/<- %ebp 4/r32/esp
 4238     # setup
 4239     (clear-stream _test-input-stream)
 4240     (clear-stream $_test-input-buffered-file->buffer)
 4241     (clear-stream _test-output-stream)
 4242     (clear-stream $_test-output-buffered-file->buffer)
 4243     #
 4244     (write _test-input-stream "fn foo {\n")
 4245     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
 4246     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
 4247     (write _test-input-stream "  y <- increment\n")
 4248     (write _test-input-stream "}\n")
 4249     # convert
 4250     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4251     (flush _test-output-buffered-file)
 4252 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4258     # check output
 4259     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-do-not-spill-same-register-in-block/0")
 4260     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-do-not-spill-same-register-in-block/1")
 4261     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-do-not-spill-same-register-in-block/2")
 4262     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-do-not-spill-same-register-in-block/3")
 4263     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-do-not-spill-same-register-in-block/4")
 4264     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-do-not-spill-same-register-in-block/5")
 4265     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-do-not-spill-same-register-in-block/6")
 4266     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-do-not-spill-same-register-in-block/7")
 4267     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 4/imm32"  "F - test-do-not-spill-same-register-in-block/8")
 4268     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-do-not-spill-same-register-in-block/9")
 4269     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-do-not-spill-same-register-in-block/10")
 4270     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-do-not-spill-same-register-in-block/11")
 4271     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-do-not-spill-same-register-in-block/12")
 4272     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-do-not-spill-same-register-in-block/13")
 4273     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-do-not-spill-same-register-in-block/14")
 4274     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-do-not-spill-same-register-in-block/15")
 4275     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-do-not-spill-same-register-in-block/16")
 4276     # . epilogue
 4277     89/<- %esp 5/r32/ebp
 4278     5d/pop-to-ebp
 4279     c3/return
 4280 
 4281 test-spill-different-register-in-block:
 4282     # . prologue
 4283     55/push-ebp
 4284     89/<- %ebp 4/r32/esp
 4285     # setup
 4286     (clear-stream _test-input-stream)
 4287     (clear-stream $_test-input-buffered-file->buffer)
 4288     (clear-stream _test-output-stream)
 4289     (clear-stream $_test-output-buffered-file->buffer)
 4290     #
 4291     (write _test-input-stream "fn foo {\n")
 4292     (write _test-input-stream "  var x/eax: int <- copy 3\n")
 4293     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
 4294     (write _test-input-stream "  y <- increment\n")
 4295     (write _test-input-stream "}\n")
 4296     # convert
 4297     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4298     (flush _test-output-buffered-file)
 4299 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4305     # check output
 4306     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-spill-different-register-in-block/0")
 4307     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-spill-different-register-in-block/1")
 4308     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-spill-different-register-in-block/2")
 4309     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-spill-different-register-in-block/3")
 4310     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-spill-different-register-in-block/4")
 4311     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-spill-different-register-in-block/5")
 4312     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-spill-different-register-in-block/6")
 4313     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 3/imm32"  "F - test-spill-different-register-in-block/7")
 4314     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-spill-different-register-in-block/8")
 4315     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 4/imm32"  "F - test-spill-different-register-in-block/9")
 4316     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-spill-different-register-in-block/10")
 4317     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-spill-different-register-in-block/11")
 4318     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-spill-different-register-in-block/12")
 4319     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-spill-different-register-in-block/13")
 4320     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-spill-different-register-in-block/14")
 4321     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-spill-different-register-in-block/15")
 4322     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-spill-different-register-in-block/16")
 4323     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-spill-different-register-in-block/17")
 4324     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-spill-different-register-in-block/18")
 4325     # . epilogue
 4326     89/<- %esp 5/r32/ebp
 4327     5d/pop-to-ebp
 4328     c3/return
 4329 
 4330 test-convert-function-with-branches-in-block:
 4331     # . prologue
 4332     55/push-ebp
 4333     89/<- %ebp 4/r32/esp
 4334     # setup
 4335     (clear-stream _test-input-stream)
 4336     (clear-stream $_test-input-buffered-file->buffer)
 4337     (clear-stream _test-output-stream)
 4338     (clear-stream $_test-output-buffered-file->buffer)
 4339     #
 4340     (write _test-input-stream "fn foo x: int {\n")
 4341     (write _test-input-stream "  {\n")
 4342     (write _test-input-stream "    break-if->=\n")
 4343     (write _test-input-stream "    loop-if-addr<\n")
 4344     (write _test-input-stream "    increment x\n")
 4345     (write _test-input-stream "    loop\n")
 4346     (write _test-input-stream "  }\n")
 4347     (write _test-input-stream "}\n")
 4348     # convert
 4349     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4350     (flush _test-output-buffered-file)
 4351 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4357     # check output
 4358     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-in-block/0")
 4359     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-in-block/1")
 4360     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-in-block/2")
 4361     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-in-block/3")
 4362     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-in-block/4")
 4363     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-in-block/5")
 4364     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-in-block/6")
 4365     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-in-block/7")
 4366     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/8")
 4367     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-in-block/9")
 4368     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-with-branches-in-block/10")
 4369     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/11")
 4370     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/12")
 4371     (check-next-stream-line-equal _test-output-stream "        0f 83/jump-if-addr>= break/disp32"  "F - test-convert-function-with-branches-in-block/13")
 4372     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:loop/disp32"  "F - test-convert-function-with-branches-in-block/14")
 4373     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/15")
 4374     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-branches-in-block/16")
 4375     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-branches-in-block/17")
 4376     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-in-block/18")
 4377     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-in-block/19")
 4378     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-in-block/20")
 4379     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-in-block/21")
 4380     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-in-block/22")
 4381     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-in-block/23")
 4382     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-in-block/24")
 4383     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-in-block/25")
 4384     # . epilogue
 4385     89/<- %esp 5/r32/ebp
 4386     5d/pop-to-ebp
 4387     c3/return
 4388 
 4389 test-convert-function-with-branches-in-block-2:
 4390     # . prologue
 4391     55/push-ebp
 4392     89/<- %ebp 4/r32/esp
 4393     # setup
 4394     (clear-stream _test-input-stream)
 4395     (clear-stream $_test-input-buffered-file->buffer)
 4396     (clear-stream _test-output-stream)
 4397     (clear-stream $_test-output-buffered-file->buffer)
 4398     #
 4399     (write _test-input-stream "fn foo x: int {\n")
 4400     (write _test-input-stream "  {\n")
 4401     (write _test-input-stream "    break-if->=\n")
 4402     (write _test-input-stream "    loop-if-float<\n")
 4403     (write _test-input-stream "    increment x\n")
 4404     (write _test-input-stream "    loop\n")
 4405     (write _test-input-stream "  }\n")
 4406     (write _test-input-stream "}\n")
 4407     # convert
 4408     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4409     (flush _test-output-buffered-file)
 4410 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4416     # check output
 4417     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-in-block/0")
 4418     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-in-block/1")
 4419     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-in-block/2")
 4420     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-in-block/3")
 4421     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-in-block/4")
 4422     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-in-block/5")
 4423     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-in-block/6")
 4424     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-in-block/7")
 4425     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/8")
 4426     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-in-block/9")
 4427     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-with-branches-in-block/10")
 4428     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/11")
 4429     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/12")
 4430     (check-next-stream-line-equal _test-output-stream "        0f 83/jump-if-addr>= break/disp32"  "F - test-convert-function-with-branches-in-block/13")
 4431     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:loop/disp32"  "F - test-convert-function-with-branches-in-block/14")
 4432     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/15")
 4433     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-branches-in-block/16")
 4434     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-branches-in-block/17")
 4435     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-in-block/18")
 4436     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-in-block/19")
 4437     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-in-block/20")
 4438     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-in-block/21")
 4439     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-in-block/22")
 4440     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-in-block/23")
 4441     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-in-block/24")
 4442     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-in-block/25")
 4443     # . epilogue
 4444     89/<- %esp 5/r32/ebp
 4445     5d/pop-to-ebp
 4446     c3/return
 4447 
 4448 test-convert-function-with-branches-in-named-block:
 4449     # . prologue
 4450     55/push-ebp
 4451     89/<- %ebp 4/r32/esp
 4452     # setup
 4453     (clear-stream _test-input-stream)
 4454     (clear-stream $_test-input-buffered-file->buffer)
 4455     (clear-stream _test-output-stream)
 4456     (clear-stream $_test-output-buffered-file->buffer)
 4457     #
 4458     (write _test-input-stream "fn foo x: int {\n")
 4459     (write _test-input-stream "  $bar: {\n")
 4460     (write _test-input-stream "    break-if->= $bar\n")
 4461     (write _test-input-stream "    loop-if-addr< $bar\n")
 4462     (write _test-input-stream "    increment x\n")
 4463     (write _test-input-stream "    loop\n")
 4464     (write _test-input-stream "  }\n")
 4465     (write _test-input-stream "}\n")
 4466     # convert
 4467     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4468     (flush _test-output-buffered-file)
 4469 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4475     # check output
 4476     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-in-named-block/0")
 4477     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-in-named-block/1")
 4478     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-in-named-block/2")
 4479     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-in-named-block/3")
 4480     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-in-named-block/4")
 4481     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-in-named-block/5")
 4482     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-in-named-block/6")
 4483     (check-next-stream-line-equal _test-output-stream "$bar:loop:"              "F - test-convert-function-with-branches-in-named-block/7")
 4484     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-named-block/8")
 4485     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-in-named-block/9")
 4486     (check-next-stream-line-equal _test-output-stream "        e9/jump $bar:break/disp32"  "F - test-convert-function-with-branches-in-named-block/10")
 4487     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-named-block/11")
 4488     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-named-block/12")
 4489     (check-next-stream-line-equal _test-output-stream "        0f 83/jump-if-addr>= break/disp32"  "F - test-convert-function-with-branches-in-named-block/13")
 4490     (check-next-stream-line-equal _test-output-stream "        e9/jump $bar:loop/disp32"  "F - test-convert-function-with-branches-in-named-block/14")
 4491     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-named-block/15")
 4492     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-branches-in-named-block/16")
 4493     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"   "F - test-convert-function-with-branches-in-named-block/17")
 4494     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-in-named-block/18")
 4495     (check-next-stream-line-equal _test-output-stream "$bar:break:"             "F - test-convert-function-with-branches-in-named-block/19")
 4496     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-in-named-block/20")
 4497     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-in-named-block/21")
 4498     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-in-named-block/22")
 4499     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-in-named-block/23")
 4500     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-in-named-block/24")
 4501     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-in-named-block/25")
 4502     # . epilogue
 4503     89/<- %esp 5/r32/ebp
 4504     5d/pop-to-ebp
 4505     c3/return
 4506 
 4507 test-convert-function-with-var-in-nested-block:
 4508     # . prologue
 4509     55/push-ebp
 4510     89/<- %ebp 4/r32/esp
 4511     # setup
 4512     (clear-stream _test-input-stream)
 4513     (clear-stream $_test-input-buffered-file->buffer)
 4514     (clear-stream _test-output-stream)
 4515     (clear-stream $_test-output-buffered-file->buffer)
 4516     #
 4517     (write _test-input-stream "fn foo x: int {\n")
 4518     (write _test-input-stream "  {\n")
 4519     (write _test-input-stream "    {\n")
 4520     (write _test-input-stream "      var x: int\n")
 4521     (write _test-input-stream "      increment x\n")
 4522     (write _test-input-stream "    }\n")
 4523     (write _test-input-stream "  }\n")
 4524     (write _test-input-stream "}\n")
 4525     # convert
 4526     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4527     (flush _test-output-buffered-file)
 4528 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4534     # check output
 4535     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-var-in-nested-block/0")
 4536     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-var-in-nested-block/1")
 4537     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-var-in-nested-block/2")
 4538     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-var-in-nested-block/3")
 4539     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-var-in-nested-block/4")
 4540     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-var-in-nested-block/5")
 4541     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-var-in-nested-block/6")
 4542     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-var-in-nested-block/7")
 4543     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-var-in-nested-block/8")
 4544     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-var-in-nested-block/9")
 4545     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-var-in-nested-block/10")
 4546     (check-next-stream-line-equal _test-output-stream "        ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-var-in-nested-block/11")
 4547     (check-next-stream-line-equal _test-output-stream "        81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-var-in-nested-block/12")
 4548     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-var-in-nested-block/13")
 4549     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-var-in-nested-block/14")
 4550     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-var-in-nested-block/15")
 4551     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-var-in-nested-block/16")
 4552     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-var-in-nested-block/17")
 4553     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-var-in-nested-block/18")
 4554     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-var-in-nested-block/19")
 4555     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-var-in-nested-block/20")
 4556     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-var-in-nested-block/21")
 4557     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-var-in-nested-block/22")
 4558     # . epilogue
 4559     89/<- %esp 5/r32/ebp
 4560     5d/pop-to-ebp
 4561     c3/return
 4562 
 4563 test-convert-function-with-multiple-vars-in-nested-blocks:
 4564     # . prologue
 4565     55/push-ebp
 4566     89/<- %ebp 4/r32/esp
 4567     # setup
 4568     (clear-stream _test-input-stream)
 4569     (clear-stream $_test-input-buffered-file->buffer)
 4570     (clear-stream _test-output-stream)
 4571     (clear-stream $_test-output-buffered-file->buffer)
 4572     #
 4573     (write _test-input-stream "fn foo x: int {\n")
 4574     (write _test-input-stream "  {\n")
 4575     (write _test-input-stream "    var x/eax: int <- copy 0\n")
 4576     (write _test-input-stream "    {\n")
 4577     (write _test-input-stream "      var y: int\n")
 4578     (write _test-input-stream "      x <- add y\n")
 4579     (write _test-input-stream "    }\n")
 4580     (write _test-input-stream "  }\n")
 4581     (write _test-input-stream "}\n")
 4582     # convert
 4583     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4584     (flush _test-output-buffered-file)
 4585 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4591     # check output
 4592     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-multiple-vars-in-nested-blocks/0")
 4593     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-multiple-vars-in-nested-blocks/1")
 4594     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-multiple-vars-in-nested-blocks/2")
 4595     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/3")
 4596     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-multiple-vars-in-nested-blocks/4")
 4597     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/5")
 4598     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-multiple-vars-in-nested-blocks/6")
 4599     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/7")
 4600     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %eax"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/8")
 4601     (check-next-stream-line-equal _test-output-stream "      b8/copy-to-eax 0/imm32"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/9")
 4602     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-multiple-vars-in-nested-blocks/10")
 4603     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/11")
 4604     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-multiple-vars-in-nested-blocks/12")
 4605     (check-next-stream-line-equal _test-output-stream "        03/add *(ebp+0xfffffff8) 0x00000000/r32"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/13")
 4606     (check-next-stream-line-equal _test-output-stream "        81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/14")
 4607     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-multiple-vars-in-nested-blocks/15")
 4608     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/16")
 4609     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %eax"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/17")
 4610     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-multiple-vars-in-nested-blocks/18")
 4611     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/19")
 4612     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-multiple-vars-in-nested-blocks/20")
 4613     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/21")
 4614     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-multiple-vars-in-nested-blocks/22")
 4615     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/23")
 4616     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-multiple-vars-in-nested-blocks/24")
 4617     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-multiple-vars-in-nested-blocks/25")
 4618     # . epilogue
 4619     89/<- %esp 5/r32/ebp
 4620     5d/pop-to-ebp
 4621     c3/return
 4622 
 4623 test-convert-function-with-branches-and-local-vars:
 4624     # A conditional 'break' after a 'var' in a block is converted into a
 4625     # nested block that performs all necessary cleanup before jumping. This
 4626     # results in some ugly code duplication.
 4627     # . prologue
 4628     55/push-ebp
 4629     89/<- %ebp 4/r32/esp
 4630     # setup
 4631     (clear-stream _test-input-stream)
 4632     (clear-stream $_test-input-buffered-file->buffer)
 4633     (clear-stream _test-output-stream)
 4634     (clear-stream $_test-output-buffered-file->buffer)
 4635     #
 4636     (write _test-input-stream "fn foo {\n")
 4637     (write _test-input-stream "  {\n")
 4638     (write _test-input-stream "    var x: int\n")
 4639     (write _test-input-stream "    break-if->=\n")
 4640     (write _test-input-stream "    increment x\n")
 4641     (write _test-input-stream "  }\n")
 4642     (write _test-input-stream "}\n")
 4643     # convert
 4644     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4645     (flush _test-output-buffered-file)
 4646 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4652     # check output
 4653     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-and-local-vars/0")
 4654     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-and-local-vars/1")
 4655     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-and-local-vars/2")
 4656     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-and-local-vars/3")
 4657     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-and-local-vars/4")
 4658     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-and-local-vars/5")
 4659     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-and-local-vars/6")
 4660     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-and-local-vars/7")
 4661     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-branches-and-local-vars/8")
 4662     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-and-local-vars/9")
 4663     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-and-local-vars/10")
 4664     (check-next-stream-line-equal _test-output-stream "        81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-branches-and-local-vars/11")
 4665     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-with-branches-and-local-vars/12")
 4666     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-and-local-vars/13")
 4667     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-branches-and-local-vars/14")
 4668     (check-next-stream-line-equal _test-output-stream "      81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-branches-and-local-vars/15")
 4669     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-and-local-vars/16")
 4670     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-and-local-vars/17")
 4671     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-and-local-vars/18")
 4672     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-and-local-vars/19")
 4673     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-and-local-vars/20")
 4674     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-and-local-vars/21")
 4675     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-and-local-vars/22")
 4676     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-and-local-vars/23")
 4677     # . epilogue
 4678     89/<- %esp 5/r32/ebp
 4679     5d/pop-to-ebp
 4680     c3/return
 4681 
 4682 test-convert-function-with-conditional-loops-and-local-vars:
 4683     # A conditional 'loop' after a 'var' in a block is converted into a nested
 4684     # block that performs all necessary cleanup before jumping. This results
 4685     # in some ugly code duplication.
 4686     # . prologue
 4687     55/push-ebp
 4688     89/<- %ebp 4/r32/esp
 4689     # setup
 4690     (clear-stream _test-input-stream)
 4691     (clear-stream $_test-input-buffered-file->buffer)
 4692     (clear-stream _test-output-stream)
 4693     (clear-stream $_test-output-buffered-file->buffer)
 4694     #
 4695     (write _test-input-stream "fn foo {\n")
 4696     (write _test-input-stream "  {\n")
 4697     (write _test-input-stream "    var x: int\n")
 4698     (write _test-input-stream "    loop-if->=\n")
 4699     (write _test-input-stream "    increment x\n")
 4700     (write _test-input-stream "  }\n")
 4701     (write _test-input-stream "}\n")
 4702     # convert
 4703     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4704     (flush _test-output-buffered-file)
 4705 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4711     # check output
 4712     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-conditional-loops-and-local-vars/0")
 4713     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-conditional-loops-and-local-vars/1")
 4714     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-conditional-loops-and-local-vars/2")
 4715     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-conditional-loops-and-local-vars/3")
 4716     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-conditional-loops-and-local-vars/4")
 4717     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-conditional-loops-and-local-vars/5")
 4718     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-conditional-loops-and-local-vars/6")
 4719     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-conditional-loops-and-local-vars/7")
 4720     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-conditional-loops-and-local-vars/8")
 4721     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-conditional-loops-and-local-vars/9")
 4722     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-conditional-loops-and-local-vars/10")
 4723     (check-next-stream-line-equal _test-output-stream "        81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-conditional-loops-and-local-vars/11")
 4724     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:loop/disp32"  "F - test-convert-function-with-conditional-loops-and-local-vars/12")
 4725     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-conditional-loops-and-local-vars/13")
 4726     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-conditional-loops-and-local-vars/14")
 4727     (check-next-stream-line-equal _test-output-stream "      81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-conditional-loops-and-local-vars/15")
 4728     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-conditional-loops-and-local-vars/16")
 4729     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-conditional-loops-and-local-vars/17")
 4730     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-conditional-loops-and-local-vars/18")
 4731     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-conditional-loops-and-local-vars/19")
 4732     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-conditional-loops-and-local-vars/20")
 4733     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-conditional-loops-and-local-vars/21")
 4734     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-conditional-loops-and-local-vars/22")
 4735     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-conditional-loops-and-local-vars/23")
 4736     # . epilogue
 4737     89/<- %esp 5/r32/ebp
 4738     5d/pop-to-ebp
 4739     c3/return
 4740 
 4741 test-convert-function-with-unconditional-loops-and-local-vars:
 4742     # An unconditional 'loop' after a 'var' in a block is emitted _after_ the
 4743     # regular block cleanup. Any instructions after 'loop' are dead and
 4744     # therefore skipped.
 4745     # . prologue
 4746     55/push-ebp
 4747     89/<- %ebp 4/r32/esp
 4748     # setup
 4749     (clear-stream _test-input-stream)
 4750     (clear-stream $_test-input-buffered-file->buffer)
 4751     (clear-stream _test-output-stream)
 4752     (clear-stream $_test-output-buffered-file->buffer)
 4753     #
 4754     (write _test-input-stream "fn foo {\n")
 4755     (write _test-input-stream "  {\n")
 4756     (write _test-input-stream "    var x: int\n")
 4757     (write _test-input-stream "    loop\n")
 4758     (write _test-input-stream "    increment x\n")
 4759     (write _test-input-stream "  }\n")
 4760     (write _test-input-stream "}\n")
 4761     # convert
 4762     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4763     (flush _test-output-buffered-file)
 4764 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4770     # check output
 4771     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-unconditional-loops-and-local-vars/0")
 4772     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-unconditional-loops-and-local-vars/1")
 4773     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-unconditional-loops-and-local-vars/2")
 4774     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-unconditional-loops-and-local-vars/3")
 4775     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-unconditional-loops-and-local-vars/4")
 4776     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-unconditional-loops-and-local-vars/5")
 4777     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-unconditional-loops-and-local-vars/6")
 4778     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-unconditional-loops-and-local-vars/7")
 4779     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-unconditional-loops-and-local-vars/8")
 4780     (check-next-stream-line-equal _test-output-stream "      81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-unconditional-loops-and-local-vars/9")
 4781     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-unconditional-loops-and-local-vars/10")
 4782     # not emitted:                                           ff 0/subop/increment *(ebp+0xfffffffc)
 4783     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-unconditional-loops-and-local-vars/11")
 4784     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-unconditional-loops-and-local-vars/12")
 4785     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-unconditional-loops-and-local-vars/13")
 4786     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-unconditional-loops-and-local-vars/14")
 4787     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-unconditional-loops-and-local-vars/15")
 4788     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-unconditional-loops-and-local-vars/16")
 4789     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-unconditional-loops-and-local-vars/17")
 4790     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-unconditional-loops-and-local-vars/18")
 4791     # . epilogue
 4792     89/<- %esp 5/r32/ebp
 4793     5d/pop-to-ebp
 4794     c3/return
 4795 
 4796 test-convert-function-with-branches-and-loops-and-local-vars:
 4797     # . prologue
 4798     55/push-ebp
 4799     89/<- %ebp 4/r32/esp
 4800     # setup
 4801     (clear-stream _test-input-stream)
 4802     (clear-stream $_test-input-buffered-file->buffer)
 4803     (clear-stream _test-output-stream)
 4804     (clear-stream $_test-output-buffered-file->buffer)
 4805     #
 4806     (write _test-input-stream "fn foo {\n")
 4807     (write _test-input-stream "  {\n")
 4808     (write _test-input-stream "    var x: int\n")
 4809     (write _test-input-stream "    break-if->=\n")
 4810     (write _test-input-stream "    increment x\n")
 4811     (write _test-input-stream "    loop\n")
 4812     (write _test-input-stream "  }\n")
 4813     (write _test-input-stream "}\n")
 4814     # convert
 4815     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4816     (flush _test-output-buffered-file)
 4817 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4823     # check output
 4824     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-and-loops-and-local-vars/0")
 4825     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-and-loops-and-local-vars/1")
 4826     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-and-loops-and-local-vars/2")
 4827     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-and-loops-and-local-vars/3")
 4828     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-and-loops-and-local-vars/4")
 4829     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-and-loops-and-local-vars/5")
 4830     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-and-loops-and-local-vars/6")
 4831     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-and-loops-and-local-vars/7")
 4832     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-branches-and-loops-and-local-vars/8")
 4833     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-and-loops-and-local-vars/9")
 4834     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-and-loops-and-local-vars/10")
 4835     (check-next-stream-line-equal _test-output-stream "        81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-branches-and-loops-and-local-vars/11")
 4836     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-with-branches-and-loops-and-local-vars/12")
 4837     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-and-loops-and-local-vars/13")
 4838     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-branches-and-loops-and-local-vars/14")
 4839     (check-next-stream-line-equal _test-output-stream "      81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-branches-and-loops-and-local-vars/15")
 4840     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-branches-and-loops-and-local-vars/16")
 4841     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-and-loops-and-local-vars/17")
 4842     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-and-loops-and-local-vars/18")
 4843     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-and-loops-and-local-vars/19")
 4844     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-and-loops-and-local-vars/20")
 4845     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-and-loops-and-local-vars/21")
 4846     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-and-loops-and-local-vars/22")
 4847     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-and-loops-and-local-vars/23")
 4848     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-and-loops-and-local-vars/24")
 4849     # . epilogue
 4850     89/<- %esp 5/r32/ebp
 4851     5d/pop-to-ebp
 4852     c3/return
 4853 
 4854 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars:
 4855     # . prologue
 4856     55/push-ebp
 4857     89/<- %ebp 4/r32/esp
 4858     # setup
 4859     (clear-stream _test-input-stream)
 4860     (clear-stream $_test-input-buffered-file->buffer)
 4861     (clear-stream _test-output-stream)
 4862     (clear-stream $_test-output-buffered-file->buffer)
 4863     #
 4864     (write _test-input-stream "fn foo {\n")
 4865     (write _test-input-stream "  a: {\n")
 4866     (write _test-input-stream "    var x: int\n")
 4867     (write _test-input-stream "    {\n")
 4868     (write _test-input-stream "      var y: int\n")
 4869     (write _test-input-stream "      break-if->= a\n")
 4870     (write _test-input-stream "      increment x\n")
 4871     (write _test-input-stream "      loop\n")
 4872     (write _test-input-stream "    }\n")
 4873     (write _test-input-stream "  }\n")
 4874     (write _test-input-stream "}\n")
 4875     # convert
 4876     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4877     (flush _test-output-buffered-file)
 4878 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4884     # check output
 4885     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/0")
 4886     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/1")
 4887     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/2")
 4888     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/3")
 4889     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/4")
 4890     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/5")
 4891     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/6")
 4892     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/7")
 4893     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/8")
 4894     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/9")
 4895     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/10")
 4896     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/11")
 4897     (check-next-stream-line-equal _test-output-stream "        {"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/12")
 4898     (check-next-stream-line-equal _test-output-stream "          0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/13")
 4899     (check-next-stream-line-equal _test-output-stream "          81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/14")
 4900     (check-next-stream-line-equal _test-output-stream "          81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/15")
 4901     (check-next-stream-line-equal _test-output-stream "          e9/jump a:break/disp32"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/16")
 4902     (check-next-stream-line-equal _test-output-stream "        }"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/17")
 4903     (check-next-stream-line-equal _test-output-stream "        ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/18")
 4904     (check-next-stream-line-equal _test-output-stream "        81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/19")
 4905     (check-next-stream-line-equal _test-output-stream "        e9/jump loop/disp32"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/20")
 4906     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/21")
 4907     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/22")
 4908     (check-next-stream-line-equal _test-output-stream "      81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/23")
 4909     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/24")
 4910     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/25")
 4911     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/26")
 4912     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/27")
 4913     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/28")
 4914     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/29")
 4915     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/30")
 4916     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/31")
 4917     # . epilogue
 4918     89/<- %esp 5/r32/ebp
 4919     5d/pop-to-ebp
 4920     c3/return
 4921 
 4922 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2:
 4923     # . prologue
 4924     55/push-ebp
 4925     89/<- %ebp 4/r32/esp
 4926     # setup
 4927     (clear-stream _test-input-stream)
 4928     (clear-stream $_test-input-buffered-file->buffer)
 4929     (clear-stream _test-output-stream)
 4930     (clear-stream $_test-output-buffered-file->buffer)
 4931     # non-local conditional branch from a block without a local variable,
 4932     # unwinding a local on the stack
 4933     (write _test-input-stream "fn foo {\n")
 4934     (write _test-input-stream "  a: {\n")
 4935     (write _test-input-stream "    var x: int\n")
 4936     (write _test-input-stream "    {\n")
 4937     (write _test-input-stream "      break-if->= a\n")
 4938     (write _test-input-stream "    }\n")
 4939     (write _test-input-stream "  }\n")
 4940     (write _test-input-stream "}\n")
 4941     # convert
 4942     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 4943     (flush _test-output-buffered-file)
 4944 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 4950     # check output
 4951     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/0")
 4952     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/1")
 4953     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/2")
 4954     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/3")
 4955     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/4")
 4956     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/5")
 4957     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/6")
 4958     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/7")
 4959     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/8")
 4960     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/9")
 4961     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/10")
 4962     (check-next-stream-line-equal _test-output-stream "        {"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/11")
 4963     (check-next-stream-line-equal _test-output-stream "          0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/12")
 4964     (check-next-stream-line-equal _test-output-stream "          81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/13")
 4965     (check-next-stream-line-equal _test-output-stream "          e9/jump a:break/disp32"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/14")
 4966     (check-next-stream-line-equal _test-output-stream "        }"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/15")
 4967     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/16")
 4968     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/17")
 4969     (check-next-stream-line-equal _test-output-stream "      81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/18")
 4970     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/19")
 4971     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/20")
 4972     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/21")
 4973     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/22")
 4974     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/23")
 4975     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/24")
 4976     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/25")
 4977     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/26")
 4978     # . epilogue
 4979     89/<- %esp 5/r32/ebp
 4980     5d/pop-to-ebp
 4981     c3/return
 4982 
 4983 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3:
 4984     # . prologue
 4985     55/push-ebp
 4986     89/<- %ebp 4/r32/esp
 4987     # setup
 4988     (clear-stream _test-input-stream)
 4989     (clear-stream $_test-input-buffered-file->buffer)
 4990     (clear-stream _test-output-stream)
 4991     (clear-stream $_test-output-buffered-file->buffer)
 4992     # non-local unconditional branch from a block without a local variable,
 4993     # unwinding a local on the stack
 4994     (write _test-input-stream "fn foo {\n")
 4995     (write _test-input-stream "  a: {\n")
 4996     (write _test-input-stream "    var x: int\n")
 4997     (write _test-input-stream "    {\n")
 4998     (write _test-input-stream "      break a\n")
 4999     (write _test-input-stream "    }\n")
 5000     (write _test-input-stream "  }\n")
 5001     (write _test-input-stream "}\n")
 5002     # convert
 5003     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5004     (flush _test-output-buffered-file)
 5005 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5011     # check output
 5012     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/0")
 5013     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/1")
 5014     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/2")
 5015     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/3")
 5016     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/4")
 5017     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/5")
 5018     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/6")
 5019     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/7")
 5020     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/8")
 5021     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/9")
 5022     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/10")
 5023     (check-next-stream-line-equal _test-output-stream "        81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/11")
 5024     (check-next-stream-line-equal _test-output-stream "        e9/jump a:break/disp32"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/12")
 5025     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/14")
 5026     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/15")
 5027     (check-next-stream-line-equal _test-output-stream "      81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/16")
 5028     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/17")
 5029     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/18")
 5030     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/19")
 5031     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/20")
 5032     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/21")
 5033     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/22")
 5034     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/23")
 5035     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/24")
 5036     # . epilogue
 5037     89/<- %esp 5/r32/ebp
 5038     5d/pop-to-ebp
 5039     c3/return
 5040 
 5041 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4:
 5042     # . prologue
 5043     55/push-ebp
 5044     89/<- %ebp 4/r32/esp
 5045     # setup
 5046     (clear-stream _test-input-stream)
 5047     (clear-stream $_test-input-buffered-file->buffer)
 5048     (clear-stream _test-output-stream)
 5049     (clear-stream $_test-output-buffered-file->buffer)
 5050     #
 5051     (write _test-input-stream "fn foo {\n")
 5052     (write _test-input-stream "  a: {\n")
 5053     (write _test-input-stream "    var x/esi: int <- copy 0\n")
 5054     (write _test-input-stream "    {\n")
 5055     (write _test-input-stream "      break a\n")
 5056     (write _test-input-stream "    }\n")
 5057     (write _test-input-stream "  }\n")
 5058     (write _test-input-stream "}\n")
 5059     # convert
 5060     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5061     (flush _test-output-buffered-file)
 5062 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5068     # check output
 5069     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/0")
 5070     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/1")
 5071     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/2")
 5072     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/3")
 5073     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/4")
 5074     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/5")
 5075     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/6")
 5076     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/7")
 5077     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %esi"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/8")
 5078     (check-next-stream-line-equal _test-output-stream "      be/copy-to-esi 0/imm32"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/9")
 5079     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/10")
 5080     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/11")
 5081     (check-next-stream-line-equal _test-output-stream "        8f 0/subop/pop %esi"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/12")
 5082     (check-next-stream-line-equal _test-output-stream "        e9/jump a:break/disp32"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/13")
 5083     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/14")
 5084     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/15")
 5085     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %esi"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/16")
 5086     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/17")
 5087     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/18")
 5088     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/19")
 5089     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/20")
 5090     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/21")
 5091     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/22")
 5092     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/23")
 5093     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/24")
 5094     # . epilogue
 5095     89/<- %esp 5/r32/ebp
 5096     5d/pop-to-ebp
 5097     c3/return
 5098 
 5099 test-convert-function-with-nonlocal-unconditional-break-and-local-vars:
 5100     # . prologue
 5101     55/push-ebp
 5102     89/<- %ebp 4/r32/esp
 5103     # setup
 5104     (clear-stream _test-input-stream)
 5105     (clear-stream $_test-input-buffered-file->buffer)
 5106     (clear-stream _test-output-stream)
 5107     (clear-stream $_test-output-buffered-file->buffer)
 5108     #
 5109     (write _test-input-stream "fn foo {\n")
 5110     (write _test-input-stream "  a: {\n")
 5111     (write _test-input-stream "    var x: int\n")
 5112     (write _test-input-stream "    {\n")
 5113     (write _test-input-stream "      var y: int\n")
 5114     (write _test-input-stream "      break a\n")
 5115     (write _test-input-stream "      increment x\n")
 5116     (write _test-input-stream "    }\n")
 5117     (write _test-input-stream "  }\n")
 5118     (write _test-input-stream "}\n")
 5119     # convert
 5120     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5121     (flush _test-output-buffered-file)
 5122 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5128     # check output
 5129     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/0")
 5130     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/1")
 5131     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/2")
 5132     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/3")
 5133     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/4")
 5134     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/5")
 5135     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/6")
 5136     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/7")
 5137     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/8")
 5138     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/9")
 5139     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/10")
 5140     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/11")
 5141     (check-next-stream-line-equal _test-output-stream "        81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/12")
 5142     (check-next-stream-line-equal _test-output-stream "        81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/13")
 5143     (check-next-stream-line-equal _test-output-stream "        e9/jump a:break/disp32"  "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/14")
 5144     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/15")
 5145     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/16")
 5146     (check-next-stream-line-equal _test-output-stream "      81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/17")
 5147     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/18")
 5148     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/19")
 5149     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/20")
 5150     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/21")
 5151     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/22")
 5152     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/23")
 5153     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/24")
 5154     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/25")
 5155     # . epilogue
 5156     89/<- %esp 5/r32/ebp
 5157     5d/pop-to-ebp
 5158     c3/return
 5159 
 5160 test-convert-function-with-unconditional-break-and-local-vars:
 5161     # . prologue
 5162     55/push-ebp
 5163     89/<- %ebp 4/r32/esp
 5164     # setup
 5165     (clear-stream _test-input-stream)
 5166     (clear-stream $_test-input-buffered-file->buffer)
 5167     (clear-stream _test-output-stream)
 5168     (clear-stream $_test-output-buffered-file->buffer)
 5169     #
 5170     (write _test-input-stream "fn foo {\n")
 5171     (write _test-input-stream "  {\n")
 5172     (write _test-input-stream "    var x: int\n")
 5173     (write _test-input-stream "    {\n")
 5174     (write _test-input-stream "      var y: int\n")
 5175     (write _test-input-stream "      break\n")
 5176     (write _test-input-stream "      increment x\n")
 5177     (write _test-input-stream "    }\n")
 5178     (write _test-input-stream "  }\n")
 5179     (write _test-input-stream "}\n")
 5180     # convert
 5181     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5182     (flush _test-output-buffered-file)
 5183 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5189     # check output
 5190     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-unconditional-break-and-local-vars/0")
 5191     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-unconditional-break-and-local-vars/1")
 5192     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-unconditional-break-and-local-vars/2")
 5193     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-unconditional-break-and-local-vars/3")
 5194     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-unconditional-break-and-local-vars/4")
 5195     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-unconditional-break-and-local-vars/5")
 5196     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-unconditional-break-and-local-vars/6")
 5197     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-unconditional-break-and-local-vars/7")
 5198     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-unconditional-break-and-local-vars/8")
 5199     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-unconditional-break-and-local-vars/9")
 5200     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-unconditional-break-and-local-vars/10")
 5201     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-unconditional-break-and-local-vars/11")
 5202     (check-next-stream-line-equal _test-output-stream "        81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-unconditional-break-and-local-vars/12")
 5203     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-unconditional-break-and-local-vars/13")
 5204     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-unconditional-break-and-local-vars/14")
 5205     (check-next-stream-line-equal _test-output-stream "      81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-unconditional-break-and-local-vars/15")
 5206     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-unconditional-break-and-local-vars/16")
 5207     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-unconditional-break-and-local-vars/17")
 5208     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-unconditional-break-and-local-vars/18")
 5209     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-unconditional-break-and-local-vars/19")
 5210     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-unconditional-break-and-local-vars/20")
 5211     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-unconditional-break-and-local-vars/21")
 5212     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-unconditional-break-and-local-vars/22")
 5213     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-unconditional-break-and-local-vars/23")
 5214     # . epilogue
 5215     89/<- %esp 5/r32/ebp
 5216     5d/pop-to-ebp
 5217     c3/return
 5218 
 5219 test-convert-function-with-nonlocal-unconditional-loop-and-local-vars:
 5220     # . prologue
 5221     55/push-ebp
 5222     89/<- %ebp 4/r32/esp
 5223     # setup
 5224     (clear-stream _test-input-stream)
 5225     (clear-stream $_test-input-buffered-file->buffer)
 5226     (clear-stream _test-output-stream)
 5227     (clear-stream $_test-output-buffered-file->buffer)
 5228     #
 5229     (write _test-input-stream "fn foo {\n")
 5230     (write _test-input-stream "  a: {\n")
 5231     (write _test-input-stream "    var x: int\n")
 5232     (write _test-input-stream "    {\n")
 5233     (write _test-input-stream "      var y: int\n")
 5234     (write _test-input-stream "      loop a\n")
 5235     (write _test-input-stream "      increment x\n")
 5236     (write _test-input-stream "    }\n")
 5237     (write _test-input-stream "  }\n")
 5238     (write _test-input-stream "}\n")
 5239     # convert
 5240     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5241     (flush _test-output-buffered-file)
 5242 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5248     # check output
 5249     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/0")
 5250     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/1")
 5251     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/2")
 5252     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/3")
 5253     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/4")
 5254     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/5")
 5255     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/6")
 5256     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/7")
 5257     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/8")
 5258     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/9")
 5259     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/10")
 5260     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/11")
 5261     (check-next-stream-line-equal _test-output-stream "        81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/12")
 5262     (check-next-stream-line-equal _test-output-stream "        81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/13")
 5263     (check-next-stream-line-equal _test-output-stream "        e9/jump a:loop/disp32"  "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/14")
 5264     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/15")
 5265     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/16")
 5266     (check-next-stream-line-equal _test-output-stream "      81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/17")
 5267     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/18")
 5268     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/19")
 5269     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/20")
 5270     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/21")
 5271     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/22")
 5272     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/23")
 5273     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/24")
 5274     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/25")
 5275     # . epilogue
 5276     89/<- %esp 5/r32/ebp
 5277     5d/pop-to-ebp
 5278     c3/return
 5279 
 5280 test-convert-function-with-local-array-var-in-mem:
 5281     # . prologue
 5282     55/push-ebp
 5283     89/<- %ebp 4/r32/esp
 5284     # setup
 5285     (clear-stream _test-input-stream)
 5286     (clear-stream $_test-input-buffered-file->buffer)
 5287     (clear-stream _test-output-stream)
 5288     (clear-stream $_test-output-buffered-file->buffer)
 5289     #
 5290     (write _test-input-stream "fn foo {\n")
 5291     (write _test-input-stream "  var x: (array int 3)\n")
 5292     (write _test-input-stream "}\n")
 5293     # convert
 5294     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5295     (flush _test-output-buffered-file)
 5296 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5302     # check output
 5303     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-array-var-in-mem/0")
 5304     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-array-var-in-mem/1")
 5305     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-array-var-in-mem/2")
 5306     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-array-var-in-mem/3")
 5307     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-array-var-in-mem/4")
 5308     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-array-var-in-mem/5")
 5309     # define x
 5310     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"  "F - test-convert-function-with-local-array-var-in-mem/7")
 5311     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"  "F - test-convert-function-with-local-array-var-in-mem/8")
 5312     # reclaim x
 5313     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000010/imm32"  "F - test-convert-function-with-local-array-var-in-mem/9")
 5314     #
 5315     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-array-var-in-mem/10")
 5316     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-array-var-in-mem/11")
 5317     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-array-var-in-mem/12")
 5318     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-array-var-in-mem/13")
 5319     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-array-var-in-mem/14")
 5320     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-array-var-in-mem/15")
 5321     # . epilogue
 5322     89/<- %esp 5/r32/ebp
 5323     5d/pop-to-ebp
 5324     c3/return
 5325 
 5326 test-array-size-in-hex:
 5327     # . prologue
 5328     55/push-ebp
 5329     89/<- %ebp 4/r32/esp
 5330     # setup
 5331     (clear-stream _test-input-stream)
 5332     (clear-stream $_test-input-buffered-file->buffer)
 5333     (clear-stream _test-output-stream)
 5334     (clear-stream $_test-output-buffered-file->buffer)
 5335     (clear-stream _test-error-stream)
 5336     (clear-stream $_test-error-buffered-file->buffer)
 5337     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 5338     68/push 0/imm32
 5339     68/push 0/imm32
 5340     89/<- %edx 4/r32/esp
 5341     (tailor-exit-descriptor %edx 0x10)
 5342     #
 5343     (write _test-input-stream "fn foo {\n")
 5344     (write _test-input-stream "  var x: (array int 10)\n")
 5345     (write _test-input-stream "}\n")
 5346     # convert
 5347     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 5348     # registers except esp clobbered at this point
 5349     # restore ed
 5350     89/<- %edx 4/r32/esp
 5351     (flush _test-output-buffered-file)
 5352     (flush _test-error-buffered-file)
 5353 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5359     # check output
 5360     (check-stream-equal _test-output-stream  ""  "F - test-array-size-in-hex: output should be empty")
 5361     (check-next-stream-line-equal _test-error-stream  "literal integers are always hex in Mu; start '10' with a '0x' to be unambiguous, converting it to hexadecimal as necessary."  "F - test-array-size-in-hex: error message")
 5362     # check that stop(1) was called
 5363     (check-ints-equal *(edx+4) 2 "F - test-array-size-in-hex: exit status")
 5364     # don't restore from ebp
 5365     81 0/subop/add %esp 8/imm32
 5366     # . epilogue
 5367     5d/pop-to-ebp
 5368     c3/return
 5369 
 5370 test-convert-function-with-populate:
 5371     # . prologue
 5372     55/push-ebp
 5373     89/<- %ebp 4/r32/esp
 5374     # setup
 5375     (clear-stream _test-input-stream)
 5376     (clear-stream $_test-input-buffered-file->buffer)
 5377     (clear-stream _test-output-stream)
 5378     (clear-stream $_test-output-buffered-file->buffer)
 5379     #
 5380     (write _test-input-stream "fn foo {\n")
 5381     (write _test-input-stream "  var x/ecx: (addr handle array int) <- copy 0\n")
 5382     (write _test-input-stream "  populate x, 7\n")
 5383     (write _test-input-stream "}\n")
 5384     # convert
 5385     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5386     (flush _test-output-buffered-file)
 5387 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5393     # check output
 5394     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-populate/0")
 5395     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-populate/1")
 5396     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-populate/2")
 5397     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-populate/3")
 5398     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-populate/4")
 5399     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-populate/5")
 5400     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-populate/6")
 5401     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-function-with-populate/7")
 5402     (check-next-stream-line-equal _test-output-stream "    (allocate-array2 Heap 0x00000004 7 %ecx)"  "F - test-convert-function-with-populate/8")  # 4 = size-of(int)
 5403     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-populate/9")
 5404     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-populate/10")
 5405     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-populate/11")
 5406     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-populate/12")
 5407     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-populate/13")
 5408     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-populate/14")
 5409     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-populate/15")
 5410     # . epilogue
 5411     89/<- %esp 5/r32/ebp
 5412     5d/pop-to-ebp
 5413     c3/return
 5414 
 5415 # special-case for size(byte) when allocating array
 5416 test-convert-function-with-local-array-of-bytes-in-mem:
 5417     # . prologue
 5418     55/push-ebp
 5419     89/<- %ebp 4/r32/esp
 5420     # setup
 5421     (clear-stream _test-input-stream)
 5422     (clear-stream $_test-input-buffered-file->buffer)
 5423     (clear-stream _test-output-stream)
 5424     (clear-stream $_test-output-buffered-file->buffer)
 5425     #
 5426     (write _test-input-stream "fn foo {\n")
 5427     (write _test-input-stream "  var x: (array byte 3)\n")
 5428     (write _test-input-stream "}\n")
 5429     # convert
 5430     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5431     (flush _test-output-buffered-file)
 5432 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5438     # check output
 5439     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-array-of-bytes-in-mem/0")
 5440     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-array-of-bytes-in-mem/1")
 5441     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-array-of-bytes-in-mem/2")
 5442     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-array-of-bytes-in-mem/3")
 5443     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-array-of-bytes-in-mem/4")
 5444     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-array-of-bytes-in-mem/5")
 5445     # define x
 5446     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x00000003)"  "F - test-convert-function-with-local-array-of-bytes-in-mem/7")
 5447     (check-next-stream-line-equal _test-output-stream "    68/push 0x00000003/imm32"  "F - test-convert-function-with-local-array-of-bytes-in-mem/8")
 5448     # reclaim x
 5449     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000007/imm32"  "F - test-convert-function-with-local-array-of-bytes-in-mem/9")
 5450     #
 5451     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-array-of-bytes-in-mem/10")
 5452     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-array-of-bytes-in-mem/11")
 5453     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-array-of-bytes-in-mem/12")
 5454     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-array-of-bytes-in-mem/13")
 5455     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-array-of-bytes-in-mem/14")
 5456     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-array-of-bytes-in-mem/15")
 5457     # . epilogue
 5458     89/<- %esp 5/r32/ebp
 5459     5d/pop-to-ebp
 5460     c3/return
 5461 
 5462 test-convert-address:
 5463     # . prologue
 5464     55/push-ebp
 5465     89/<- %ebp 4/r32/esp
 5466     # setup
 5467     (clear-stream _test-input-stream)
 5468     (clear-stream $_test-input-buffered-file->buffer)
 5469     (clear-stream _test-output-stream)
 5470     (clear-stream $_test-output-buffered-file->buffer)
 5471     #
 5472     (write _test-input-stream "fn foo {\n")
 5473     (write _test-input-stream "  var a: int\n")
 5474     (write _test-input-stream "  var b/eax: (addr int) <- address a\n")
 5475     (write _test-input-stream "}\n")
 5476     # convert
 5477     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5478     (flush _test-output-buffered-file)
 5479 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5485     # check output
 5486     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-address/0")
 5487     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-address/1")
 5488     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-address/2")
 5489     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-address/3")
 5490     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-address/4")
 5491     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-address/5")
 5492     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-address/6")
 5493     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-address/7")
 5494     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp+0xfffffffc) 0x00000000/r32"  "F - test-convert-address/8")
 5495     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-address/9")
 5496     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-address/10")
 5497     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-address/11")
 5498     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-address/12")
 5499     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-address/13")
 5500     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-address/14")
 5501     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-address/15")
 5502     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-address/16")
 5503     # . epilogue
 5504     89/<- %esp 5/r32/ebp
 5505     5d/pop-to-ebp
 5506     c3/return
 5507 
 5508 test-convert-floating-point-convert:
 5509     # . prologue
 5510     55/push-ebp
 5511     89/<- %ebp 4/r32/esp
 5512     # setup
 5513     (clear-stream _test-input-stream)
 5514     (clear-stream $_test-input-buffered-file->buffer)
 5515     (clear-stream _test-output-stream)
 5516     (clear-stream $_test-output-buffered-file->buffer)
 5517     #
 5518     (write _test-input-stream "fn foo {\n")
 5519     (write _test-input-stream "  var a/eax: int <- copy 0\n")
 5520     (write _test-input-stream "  var b/xmm1: float <- convert a\n")
 5521     (write _test-input-stream "}\n")
 5522     # convert
 5523     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5524     (flush _test-output-buffered-file)
 5525 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5531     # check output
 5532     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-floating-point-convert/0")
 5533     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-floating-point-convert/1")
 5534     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-floating-point-convert/2")
 5535     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-floating-point-convert/3")
 5536     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-floating-point-convert/4")
 5537     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-floating-point-convert/5")
 5538     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-floating-point-convert/6")
 5539     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"  "F - test-convert-floating-point-convert/7")
 5540     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"  "F - test-convert-floating-point-convert/8")
 5541     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"  "F - test-convert-floating-point-convert/9")
 5542     (check-next-stream-line-equal _test-output-stream "    f3 0f 2a/convert-to-float %eax 0x00000001/x32"  "F - test-convert-floating-point-convert/10")
 5543     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 1/x32"  "F - test-convert-floating-point-convert/11")
 5544     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-floating-point-convert/12")
 5545     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-floating-point-convert/13")
 5546     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-floating-point-convert/14")
 5547     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-floating-point-convert/15")
 5548     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-floating-point-convert/16")
 5549     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-floating-point-convert/17")
 5550     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-floating-point-convert/18")
 5551     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-floating-point-convert/19")
 5552     # . epilogue
 5553     89/<- %esp 5/r32/ebp
 5554     5d/pop-to-ebp
 5555     c3/return
 5556 
 5557 test-convert-floating-point-convert-2:
 5558     # . prologue
 5559     55/push-ebp
 5560     89/<- %ebp 4/r32/esp
 5561     # setup
 5562     (clear-stream _test-input-stream)
 5563     (clear-stream $_test-input-buffered-file->buffer)
 5564     (clear-stream _test-output-stream)
 5565     (clear-stream $_test-output-buffered-file->buffer)
 5566     #
 5567     (write _test-input-stream "fn foo {\n")
 5568     (write _test-input-stream "  var a/eax: int <- copy 0\n")
 5569     (write _test-input-stream "  var b/xmm1: float <- convert a\n")
 5570     (write _test-input-stream "  a <- convert b\n")
 5571     (write _test-input-stream "}\n")
 5572     # convert
 5573     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5574     (flush _test-output-buffered-file)
 5575 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5581     # check output
 5582     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-floating-point-convert-2/0")
 5583     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-floating-point-convert-2/1")
 5584     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-floating-point-convert-2/2")
 5585     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-floating-point-convert-2/3")
 5586     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-floating-point-convert-2/4")
 5587     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-floating-point-convert-2/5")
 5588     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-floating-point-convert-2/6")
 5589     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"  "F - test-convert-floating-point-convert-2/7")
 5590     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"  "F - test-convert-floating-point-convert-2/8")
 5591     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"  "F - test-convert-floating-point-convert-2/9")
 5592     (check-next-stream-line-equal _test-output-stream "    f3 0f 2a/convert-to-float %eax 0x00000001/x32"  "F - test-convert-floating-point-convert-2/10")
 5593     (check-next-stream-line-equal _test-output-stream "    f3 0f 2d/convert-to-int %xmm1 0x00000000/r32"  "F - test-convert-floating-point-convert-2/11")
 5594     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 1/x32"  "F - test-convert-floating-point-convert-2/12")
 5595     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-floating-point-convert-2/13")
 5596     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-floating-point-convert-2/14")
 5597     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-floating-point-convert-2/15")
 5598     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-floating-point-convert-2/16")
 5599     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-floating-point-convert-2/17")
 5600     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-floating-point-convert-2/18")
 5601     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-floating-point-convert-2/19")
 5602     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-floating-point-convert-2/20")
 5603     # . epilogue
 5604     89/<- %esp 5/r32/ebp
 5605     5d/pop-to-ebp
 5606     c3/return
 5607 
 5608 test-convert-floating-point-operation:
 5609     # . prologue
 5610     55/push-ebp
 5611     89/<- %ebp 4/r32/esp
 5612     # setup
 5613     (clear-stream _test-input-stream)
 5614     (clear-stream $_test-input-buffered-file->buffer)
 5615     (clear-stream _test-output-stream)
 5616     (clear-stream $_test-output-buffered-file->buffer)
 5617     #
 5618     (write _test-input-stream "fn f {\n")
 5619     (write _test-input-stream "  var m: float\n")
 5620     (write _test-input-stream "  var x/xmm1: float <- copy m\n")
 5621     (write _test-input-stream "  var y/xmm5: float <- copy m\n")
 5622     (write _test-input-stream "  x <- copy y\n")
 5623     (write _test-input-stream "  copy-to m, y\n")
 5624     (write _test-input-stream "  x <- add y\n")
 5625     (write _test-input-stream "  x <- add m\n")
 5626     (write _test-input-stream "  x <- subtract y\n")
 5627     (write _test-input-stream "  x <- subtract m\n")
 5628     (write _test-input-stream "  x <- multiply y\n")
 5629     (write _test-input-stream "  x <- multiply m\n")
 5630     (write _test-input-stream "  x <- divide y\n")
 5631     (write _test-input-stream "  x <- divide m\n")
 5632     (write _test-input-stream "  x <- reciprocal y\n")
 5633     (write _test-input-stream "  x <- reciprocal m\n")
 5634     (write _test-input-stream "  x <- square-root y\n")
 5635     (write _test-input-stream "  x <- square-root m\n")
 5636     (write _test-input-stream "  x <- inverse-square-root y\n")
 5637     (write _test-input-stream "  x <- inverse-square-root m\n")
 5638     (write _test-input-stream "  x <- max y\n")
 5639     (write _test-input-stream "  x <- max m\n")
 5640     (write _test-input-stream "  x <- min y\n")
 5641     (write _test-input-stream "  x <- min m\n")
 5642     (write _test-input-stream "  compare x, y\n")
 5643     (write _test-input-stream "  compare x, m\n")
 5644     (write _test-input-stream "}\n")
 5645     # convert
 5646     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5647     (flush _test-output-buffered-file)
 5648 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5654     # check output
 5655     (check-next-stream-line-equal _test-output-stream "f:"                                                                     "F - test-convert-floating-point-operation/0")
 5656     (check-next-stream-line-equal _test-output-stream "  # . prologue"                                                         "F - test-convert-floating-point-operation/1")
 5657     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                                                          "F - test-convert-floating-point-operation/2")
 5658     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                                                 "F - test-convert-floating-point-operation/3")
 5659     (check-next-stream-line-equal _test-output-stream "  {"                                                                    "F - test-convert-floating-point-operation/4")
 5660     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"                                                    "F - test-convert-floating-point-operation/5")
 5661     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"                                                    "F - test-convert-floating-point-operation/6")
 5662     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"                                   "F - test-convert-floating-point-operation/7")
 5663     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"                                             "F - test-convert-floating-point-operation/8")
 5664     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/copy *(ebp+0xfffffffc) 0x00000001/x32"                     "F - test-convert-floating-point-operation/9")
 5665     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"                                   "F - test-convert-floating-point-operation/10")
 5666     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 5/x32"                                             "F - test-convert-floating-point-operation/11")
 5667     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/copy *(ebp+0xfffffffc) 0x00000005/x32"                     "F - test-convert-floating-point-operation/12")
 5668     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/copy %xmm1 0x00000005/x32"                                 "F - test-convert-floating-point-operation/13")
 5669     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/copy *(ebp+0xfffffffc) 0x00000005/x32"                     "F - test-convert-floating-point-operation/14")
 5670     (check-next-stream-line-equal _test-output-stream "    f3 0f 58/add %xmm5 0x00000001/x32"                                  "F - test-convert-floating-point-operation/15")
 5671     (check-next-stream-line-equal _test-output-stream "    f3 0f 58/add *(ebp+0xfffffffc) 0x00000001/x32"                      "F - test-convert-floating-point-operation/16")
 5672     (check-next-stream-line-equal _test-output-stream "    f3 0f 5c/subtract %xmm5 0x00000001/x32"                             "F - test-convert-floating-point-operation/17")
 5673     (check-next-stream-line-equal _test-output-stream "    f3 0f 5c/subtract *(ebp+0xfffffffc) 0x00000001/x32"                 "F - test-convert-floating-point-operation/18")
 5674     (check-next-stream-line-equal _test-output-stream "    f3 0f 59/multiply %xmm5 0x00000001/x32"                             "F - test-convert-floating-point-operation/19")
 5675     (check-next-stream-line-equal _test-output-stream "    f3 0f 59/multiply *(ebp+0xfffffffc) 0x00000001/x32"                 "F - test-convert-floating-point-operation/20")
 5676     (check-next-stream-line-equal _test-output-stream "    f3 0f 5e/divide %xmm5 0x00000001/x32"                               "F - test-convert-floating-point-operation/21")
 5677     (check-next-stream-line-equal _test-output-stream "    f3 0f 5e/divide *(ebp+0xfffffffc) 0x00000001/x32"                   "F - test-convert-floating-point-operation/22")
 5678     (check-next-stream-line-equal _test-output-stream "    f3 0f 53/reciprocal %xmm5 0x00000001/x32"                           "F - test-convert-floating-point-operation/23")
 5679     (check-next-stream-line-equal _test-output-stream "    f3 0f 53/reciprocal *(ebp+0xfffffffc) 0x00000001/x32"               "F - test-convert-floating-point-operation/24")
 5680     (check-next-stream-line-equal _test-output-stream "    f3 0f 51/square-root %xmm5 0x00000001/x32"                          "F - test-convert-floating-point-operation/25")
 5681     (check-next-stream-line-equal _test-output-stream "    f3 0f 51/square-root *(ebp+0xfffffffc) 0x00000001/x32"              "F - test-convert-floating-point-operation/26")
 5682     (check-next-stream-line-equal _test-output-stream "    f3 0f 52/inverse-square-root %xmm5 0x00000001/x32"                  "F - test-convert-floating-point-operation/27")
 5683     (check-next-stream-line-equal _test-output-stream "    f3 0f 52/inverse-square-root *(ebp+0xfffffffc) 0x00000001/x32"      "F - test-convert-floating-point-operation/28")
 5684     (check-next-stream-line-equal _test-output-stream "    f3 0f 5f/max %xmm5 0x00000001/x32"                                  "F - test-convert-floating-point-operation/29")
 5685     (check-next-stream-line-equal _test-output-stream "    f3 0f 5f/max *(ebp+0xfffffffc) 0x00000001/x32"                      "F - test-convert-floating-point-operation/30")
 5686     (check-next-stream-line-equal _test-output-stream "    f3 0f 5d/min %xmm5 0x00000001/x32"                                  "F - test-convert-floating-point-operation/31")
 5687     (check-next-stream-line-equal _test-output-stream "    f3 0f 5d/min *(ebp+0xfffffffc) 0x00000001/x32"                      "F - test-convert-floating-point-operation/32")
 5688     (check-next-stream-line-equal _test-output-stream "    0f 2f/compare %xmm1 0x00000005/x32"                                 "F - test-convert-floating-point-operation/33")
 5689     (check-next-stream-line-equal _test-output-stream "    0f 2f/compare *(ebp+0xfffffffc) 0x00000001/x32"                     "F - test-convert-floating-point-operation/34")
 5690     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 5/x32"                                             "F - test-convert-floating-point-operation/35")
 5691     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"                                        "F - test-convert-floating-point-operation/36")
 5692     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 1/x32"                                             "F - test-convert-floating-point-operation/37")
 5693     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"                                        "F - test-convert-floating-point-operation/38")
 5694     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"                               "F - test-convert-floating-point-operation/39")
 5695     (check-next-stream-line-equal _test-output-stream "  }"                                                                    "F - test-convert-floating-point-operation/40")
 5696     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"                                                   "F - test-convert-floating-point-operation/41")
 5697     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                                                         "F - test-convert-floating-point-operation/42")
 5698     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                                                 "F - test-convert-floating-point-operation/43")
 5699     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                                                        "F - test-convert-floating-point-operation/44")
 5700     (check-next-stream-line-equal _test-output-stream "  c3/return"                                                            "F - test-convert-floating-point-operation/45")
 5701     # . epilogue
 5702     89/<- %esp 5/r32/ebp
 5703     5d/pop-to-ebp
 5704     c3/return
 5705 
 5706 test-convert-floating-point-dereferenced:
 5707     # . prologue
 5708     55/push-ebp
 5709     89/<- %ebp 4/r32/esp
 5710     # setup
 5711     (clear-stream _test-input-stream)
 5712     (clear-stream $_test-input-buffered-file->buffer)
 5713     (clear-stream _test-output-stream)
 5714     (clear-stream $_test-output-buffered-file->buffer)
 5715     #
 5716     (write _test-input-stream "fn f {\n")
 5717     (write _test-input-stream "  var m: float\n")
 5718     (write _test-input-stream "  var x/xmm1: float <- copy m\n")
 5719     (write _test-input-stream "  var y/eax: (addr float) <- copy 0\n")
 5720     (write _test-input-stream "  x <- multiply *y\n")
 5721     (write _test-input-stream "}\n")
 5722     # convert
 5723     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5724     (flush _test-output-buffered-file)
 5725 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5731     # check output
 5732     (check-next-stream-line-equal _test-output-stream "f:"                                                                     "F - test-convert-floating-point-dereferenced/0")
 5733     (check-next-stream-line-equal _test-output-stream "  # . prologue"                                                         "F - test-convert-floating-point-dereferenced/1")
 5734     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                                                          "F - test-convert-floating-point-dereferenced/2")
 5735     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                                                 "F - test-convert-floating-point-dereferenced/3")
 5736     (check-next-stream-line-equal _test-output-stream "  {"                                                                    "F - test-convert-floating-point-dereferenced/4")
 5737     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"                                                    "F - test-convert-floating-point-dereferenced/5")
 5738     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"                                                    "F - test-convert-floating-point-dereferenced/6")
 5739     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"                                   "F - test-convert-floating-point-dereferenced/7")
 5740     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"                                             "F - test-convert-floating-point-dereferenced/8")
 5741     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/copy *(ebp+0xfffffffc) 0x00000001/x32"                     "F - test-convert-floating-point-dereferenced/9")
 5742     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                                               "F - test-convert-floating-point-dereferenced/10")
 5743     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                                             "F - test-convert-floating-point-dereferenced/11")
 5744     (check-next-stream-line-equal _test-output-stream "    f3 0f 59/multiply *eax 0x00000001/x32"                              "F - test-convert-floating-point-dereferenced/12")
 5745     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                                                "F - test-convert-floating-point-dereferenced/13")
 5746     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 1/x32"                                             "F - test-convert-floating-point-dereferenced/14")
 5747     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"                                        "F - test-convert-floating-point-dereferenced/15")
 5748     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"                               "F - test-convert-floating-point-dereferenced/16")
 5749     (check-next-stream-line-equal _test-output-stream "  }"                                                                    "F - test-convert-floating-point-dereferenced/17")
 5750     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"                                                   "F - test-convert-floating-point-dereferenced/18")
 5751     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                                                         "F - test-convert-floating-point-dereferenced/19")
 5752     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                                                 "F - test-convert-floating-point-dereferenced/20")
 5753     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                                                        "F - test-convert-floating-point-dereferenced/21")
 5754     (check-next-stream-line-equal _test-output-stream "  c3/return"                                                            "F - test-convert-floating-point-dereferenced/22")
 5755     # . epilogue
 5756     89/<- %esp 5/r32/ebp
 5757     5d/pop-to-ebp
 5758     c3/return
 5759 
 5760 test-convert-length-of-array:
 5761     # . prologue
 5762     55/push-ebp
 5763     89/<- %ebp 4/r32/esp
 5764     # setup
 5765     (clear-stream _test-input-stream)
 5766     (clear-stream $_test-input-buffered-file->buffer)
 5767     (clear-stream _test-output-stream)
 5768     (clear-stream $_test-output-buffered-file->buffer)
 5769     #
 5770     (write _test-input-stream "fn foo a: (addr array int) {\n")
 5771     (write _test-input-stream "  var b/eax: (addr array int) <- copy a\n")
 5772     (write _test-input-stream "  var c/eax: int <- length b\n")
 5773     (write _test-input-stream "}\n")
 5774     # convert
 5775     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5776     (flush _test-output-buffered-file)
 5777 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5783     # check output
 5784     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array/0")
 5785     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array/1")
 5786     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array/2")
 5787     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array/3")
 5788     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array/4")
 5789     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array/5")
 5790     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array/6")
 5791     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-length-of-array/7")
 5792     (check-next-stream-line-equal _test-output-stream "    8b/-> *eax 0x00000000/r32"  "F - test-convert-length-of-array/8")
 5793     (check-next-stream-line-equal _test-output-stream "    c1/shift 5/subop/>> %eax 0x00000002/imm8"  "F - test-convert-length-of-array/9")
 5794     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array/10")
 5795     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array/11")
 5796     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array/12")
 5797     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array/13")
 5798     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array/14")
 5799     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array/15")
 5800     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array/16")
 5801     # . epilogue
 5802     89/<- %esp 5/r32/ebp
 5803     5d/pop-to-ebp
 5804     c3/return
 5805 
 5806 # special-case for size(byte) when computing array length
 5807 test-convert-length-of-array-of-bytes:
 5808     # . prologue
 5809     55/push-ebp
 5810     89/<- %ebp 4/r32/esp
 5811     # setup
 5812     (clear-stream _test-input-stream)
 5813     (clear-stream $_test-input-buffered-file->buffer)
 5814     (clear-stream _test-output-stream)
 5815     (clear-stream $_test-output-buffered-file->buffer)
 5816     #
 5817     (write _test-input-stream "fn foo a: (addr array byte) {\n")
 5818     (write _test-input-stream "  var b/eax: (addr array byte) <- copy a\n")
 5819     (write _test-input-stream "  var c/eax: int <- length b\n")
 5820     (write _test-input-stream "}\n")
 5821     # convert
 5822     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5823     (flush _test-output-buffered-file)
 5824 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5830     # check output
 5831     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-bytes/0")
 5832     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-bytes/1")
 5833     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-bytes/2")
 5834     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array-of-bytes/3")
 5835     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-bytes/4")
 5836     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-bytes/5")
 5837     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array-of-bytes/6")
 5838     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-length-of-array-of-bytes/7")
 5839     (check-next-stream-line-equal _test-output-stream "    8b/-> *eax 0x00000000/r32"  "F - test-convert-length-of-array-of-bytes/8")
 5840     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array-of-bytes/9")
 5841     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-bytes/10")
 5842     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-bytes/11")
 5843     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-bytes/12")
 5844     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array-of-bytes/13")
 5845     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array-of-bytes/14")
 5846     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-bytes/15")
 5847     # . epilogue
 5848     89/<- %esp 5/r32/ebp
 5849     5d/pop-to-ebp
 5850     c3/return
 5851 
 5852 test-convert-length-of-array-on-stack:
 5853     # . prologue
 5854     55/push-ebp
 5855     89/<- %ebp 4/r32/esp
 5856     # setup
 5857     (clear-stream _test-input-stream)
 5858     (clear-stream $_test-input-buffered-file->buffer)
 5859     (clear-stream _test-output-stream)
 5860     (clear-stream $_test-output-buffered-file->buffer)
 5861     #
 5862     (write _test-input-stream "fn foo {\n")
 5863     (write _test-input-stream "  var a: (array int 3)\n")
 5864     (write _test-input-stream "  var b/eax: int <- length a\n")
 5865     (write _test-input-stream "}\n")
 5866     # convert
 5867     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5868     (flush _test-output-buffered-file)
 5869 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5875     # check output
 5876     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-on-stack/0")
 5877     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-on-stack/1")
 5878     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-on-stack/2")
 5879     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array-on-stack/3")
 5880     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-on-stack/4")
 5881     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-on-stack/5")
 5882     # define x
 5883     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"  "F - test-convert-length-of-array-on-stack/6")
 5884     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"  "F - test-convert-length-of-array-on-stack/7")
 5885     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array-on-stack/8")
 5886     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0xfffffff0) 0x00000000/r32"  "F - test-convert-length-of-array-on-stack/9")
 5887     (check-next-stream-line-equal _test-output-stream "    c1/shift 5/subop/>> %eax 0x00000002/imm8"  "F - test-convert-length-of-array-on-stack/10")
 5888     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array-on-stack/11")
 5889     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000010/imm32"  "F - test-convert-length-of-array-on-stack/12")
 5890     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-on-stack/13")
 5891     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-on-stack/14")
 5892     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-on-stack/15")
 5893     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array-on-stack/16")
 5894     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array-on-stack/17")
 5895     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-on-stack/18")
 5896     # . epilogue
 5897     89/<- %esp 5/r32/ebp
 5898     5d/pop-to-ebp
 5899     c3/return
 5900 
 5901 test-reg-var-def-with-read-of-same-register:
 5902     # . prologue
 5903     55/push-ebp
 5904     89/<- %ebp 4/r32/esp
 5905     # setup
 5906     (clear-stream _test-input-stream)
 5907     (clear-stream $_test-input-buffered-file->buffer)
 5908     (clear-stream _test-output-stream)
 5909     (clear-stream $_test-output-buffered-file->buffer)
 5910     (clear-stream _test-error-stream)
 5911     (clear-stream $_test-error-buffered-file->buffer)
 5912     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)  # bytes of args in call to convert-mu
 5913     68/push 0/imm32
 5914     68/push 0/imm32
 5915     89/<- %edx 4/r32/esp
 5916     (tailor-exit-descriptor %edx 0x10)
 5917     #
 5918     (write _test-input-stream "fn foo {\n")
 5919     (write _test-input-stream "  var x/eax: int <- copy 3\n")
 5920     (write _test-input-stream "  var y/eax: int <- add x\n")
 5921     (write _test-input-stream "}\n")
 5922     # convert
 5923     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 5924     # registers except esp could be clobbered at this point (though they shouldn't be)
 5925     # restore ed
 5926     89/<- %edx 4/r32/esp
 5927     (flush _test-output-buffered-file)
 5928     (flush _test-error-buffered-file)
 5929 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5935 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5941     (check-stream-equal _test-error-stream  ""  "F - test-reg-var-def-with-read-of-same-register: error stream should be empty")
 5942     # check output
 5943     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-reg-var-def-with-read-of-same-register/0")
 5944     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-reg-var-def-with-read-of-same-register/1")
 5945     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-reg-var-def-with-read-of-same-register/2")
 5946     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-reg-var-def-with-read-of-same-register/3")
 5947     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-reg-var-def-with-read-of-same-register/4")
 5948     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-reg-var-def-with-read-of-same-register/5")
 5949     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-reg-var-def-with-read-of-same-register/6")
 5950     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 3/imm32"                  "F - test-reg-var-def-with-read-of-same-register/7")
 5951     (check-next-stream-line-equal _test-output-stream "    01/add-to %eax 0x00000000/r32"           "F - test-reg-var-def-with-read-of-same-register/8")
 5952     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-reg-var-def-with-read-of-same-register/9")
 5953     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-reg-var-def-with-read-of-same-register/10")
 5954     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-reg-var-def-with-read-of-same-register/11")
 5955     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-reg-var-def-with-read-of-same-register/12")
 5956     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-reg-var-def-with-read-of-same-register/13")
 5957     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-reg-var-def-with-read-of-same-register/14")
 5958     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-reg-var-def-with-read-of-same-register/15")
 5959     # don't restore from ebp
 5960     81 0/subop/add %esp 8/imm32
 5961     # . epilogue
 5962     5d/pop-to-ebp
 5963     c3/return
 5964 
 5965 test-convert-index-into-array:
 5966     # . prologue
 5967     55/push-ebp
 5968     89/<- %ebp 4/r32/esp
 5969     # setup
 5970     (clear-stream _test-input-stream)
 5971     (clear-stream $_test-input-buffered-file->buffer)
 5972     (clear-stream _test-output-stream)
 5973     (clear-stream $_test-output-buffered-file->buffer)
 5974     #
 5975     (write _test-input-stream "fn foo {\n")
 5976     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
 5977     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 5978     (write _test-input-stream "  var x/eax: (addr int) <- index arr, idx\n")
 5979     (write _test-input-stream "}\n")
 5980     # convert
 5981     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 5982     (flush _test-output-buffered-file)
 5983 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 5989     # check output
 5990     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array/0")
 5991     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array/1")
 5992     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array/2")
 5993     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array/3")
 5994     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array/4")
 5995     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array/5")
 5996     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array/6")
 5997     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array/7")
 5998     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array/8")
 5999     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-index-into-array/9")
 6000     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds %ecx 0x00000004 *eax \"foo\" \"arr\")"  "F - test-convert-index-into-array/10")
 6001     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx<<0x00000002 + 4) 0x00000000/r32"  "F - test-convert-index-into-array/11")
 6002     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array/12")
 6003     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array/13")
 6004     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array/14")
 6005     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array/15")
 6006     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array/16")
 6007     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array/17")
 6008     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array/18")
 6009     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array/19")
 6010     # . epilogue
 6011     89/<- %esp 5/r32/ebp
 6012     5d/pop-to-ebp
 6013     c3/return
 6014 
 6015 test-convert-index-into-array-of-bytes:
 6016     # . prologue
 6017     55/push-ebp
 6018     89/<- %ebp 4/r32/esp
 6019     # setup
 6020     (clear-stream _test-input-stream)
 6021     (clear-stream $_test-input-buffered-file->buffer)
 6022     (clear-stream _test-output-stream)
 6023     (clear-stream $_test-output-buffered-file->buffer)
 6024     #
 6025     (write _test-input-stream "fn foo {\n")
 6026     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
 6027     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 6028     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, idx\n")
 6029     (write _test-input-stream "}\n")
 6030     # convert
 6031     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6032     (flush _test-output-buffered-file)
 6033 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6039     # check output
 6040     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes/0")
 6041     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes/1")
 6042     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes/2")
 6043     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-of-bytes/3")
 6044     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes/4")
 6045     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes/5")
 6046     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-of-bytes/6")
 6047     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-of-bytes/7")
 6048     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-of-bytes/8")
 6049     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-index-into-array-of-bytes/9")
 6050     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds %ecx 0x00000001 *eax \"foo\" \"arr\")"  "F - test-convert-index-into-array-of-bytes/10")
 6051     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx<<0x00000000 + 4) 0x00000000/r32"  "F - test-convert-index-into-array-of-bytes/11")
 6052     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-of-bytes/12")
 6053     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes/13")
 6054     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes/14")
 6055     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes/15")
 6056     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes/16")
 6057     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes/17")
 6058     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes/18")
 6059     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes/19")
 6060     # . epilogue
 6061     89/<- %esp 5/r32/ebp
 6062     5d/pop-to-ebp
 6063     c3/return
 6064 
 6065 test-convert-index-into-array-with-literal:
 6066     # . prologue
 6067     55/push-ebp
 6068     89/<- %ebp 4/r32/esp
 6069     # setup
 6070     (clear-stream _test-input-stream)
 6071     (clear-stream $_test-input-buffered-file->buffer)
 6072     (clear-stream _test-output-stream)
 6073     (clear-stream $_test-output-buffered-file->buffer)
 6074     #
 6075     (write _test-input-stream "fn foo {\n")
 6076     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
 6077     (write _test-input-stream "  var x/eax: (addr int) <- index arr, 2\n")
 6078     (write _test-input-stream "}\n")
 6079     # convert
 6080     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6081     (flush _test-output-buffered-file)
 6082 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6088     # check output
 6089     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-with-literal/0")
 6090     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-with-literal/1")
 6091     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-with-literal/2")
 6092     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-with-literal/3")
 6093     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-with-literal/4")
 6094     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-with-literal/5")
 6095     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-with-literal/6")
 6096     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-with-literal/7")
 6097     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds 2 0x00000004 *eax \"foo\" \"arr\")"  "F - test-convert-index-into-array-with-literal/8")
 6098                                                                                  # 2 * 4 bytes/elem + 4 bytes for size = offset 12
 6099     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + 0x0000000c) 0x00000000/r32"  "F - test-convert-index-into-array-with-literal/9")
 6100     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-with-literal/10")
 6101     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-with-literal/11")
 6102     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-with-literal/12")
 6103     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-with-literal/13")
 6104     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-with-literal/14")
 6105     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-with-literal/15")
 6106     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-with-literal/16")
 6107     # . epilogue
 6108     89/<- %esp 5/r32/ebp
 6109     5d/pop-to-ebp
 6110     c3/return
 6111 
 6112 test-convert-index-into-array-of-bytes-with-literal:
 6113     # . prologue
 6114     55/push-ebp
 6115     89/<- %ebp 4/r32/esp
 6116     # setup
 6117     (clear-stream _test-input-stream)
 6118     (clear-stream $_test-input-buffered-file->buffer)
 6119     (clear-stream _test-output-stream)
 6120     (clear-stream $_test-output-buffered-file->buffer)
 6121     #
 6122     (write _test-input-stream "fn foo {\n")
 6123     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
 6124     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, 2\n")
 6125     (write _test-input-stream "}\n")
 6126     # convert
 6127     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6128     (flush _test-output-buffered-file)
 6129 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6135     # check output
 6136     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-with-literal/0")
 6137     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-with-literal/1")
 6138     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-with-literal/2")
 6139     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-of-bytes-with-literal/3")
 6140     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-with-literal/4")
 6141     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-with-literal/5")
 6142     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-of-bytes-with-literal/6")
 6143     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-of-bytes-with-literal/7")
 6144     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds 2 0x00000001 *eax \"foo\" \"arr\")"  "F - test-convert-index-into-array-of-bytes-with-literal/8")
 6145                                                                                  # 2 * 1 byte/elem + 4 bytes for size = offset 6
 6146     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + 0x00000006) 0x00000000/r32"  "F - test-convert-index-into-array-of-bytes-with-literal/8")
 6147     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes-with-literal/9")
 6148     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-with-literal/10")
 6149     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-with-literal/11")
 6150     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-with-literal/12")
 6151     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes-with-literal/13")
 6152     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes-with-literal/14")
 6153     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-with-literal/15")
 6154     # . epilogue
 6155     89/<- %esp 5/r32/ebp
 6156     5d/pop-to-ebp
 6157     c3/return
 6158 
 6159 test-convert-index-into-array-on-stack:
 6160     # . prologue
 6161     55/push-ebp
 6162     89/<- %ebp 4/r32/esp
 6163     # setup
 6164     (clear-stream _test-input-stream)
 6165     (clear-stream $_test-input-buffered-file->buffer)
 6166     (clear-stream _test-output-stream)
 6167     (clear-stream $_test-output-buffered-file->buffer)
 6168     #
 6169     (write _test-input-stream "fn foo {\n")
 6170     (write _test-input-stream "  var arr: (array int 3)\n")
 6171     (write _test-input-stream "  var idx/eax: int <- copy 2\n")
 6172     (write _test-input-stream "  var x/eax: (addr int) <- index arr, idx\n")
 6173     (write _test-input-stream "}\n")
 6174     # convert
 6175     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6176     (flush _test-output-buffered-file)
 6177 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6183     # check output
 6184     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-on-stack/0")
 6185     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-on-stack/1")
 6186     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-on-stack/2")
 6187     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-on-stack/3")
 6188     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-on-stack/4")
 6189     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-on-stack/5")
 6190     # var arr
 6191     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"          "F - test-convert-index-into-array-on-stack/6")
 6192     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"                "F - test-convert-index-into-array-on-stack/7")
 6193     # var idx
 6194     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-on-stack/8")
 6195     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 2/imm32"                  "F - test-convert-index-into-array-on-stack/9")
 6196     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds %eax 0x00000004 *(ebp+0xfffffff0) \"foo\" \"arr\")"  "F - test-convert-index-into-array-on-stack/10")
 6197     # var x is at (ebp-0x10) + idx<<2 + 4 = ebp + idx<<2 - 0xc
 6198     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp + eax<<0x00000002 + 0xfffffff4) 0x00000000/r32"  "F - test-convert-index-into-array-on-stack/11")
 6199     # reclaim idx
 6200     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-on-stack/12")
 6201     # reclaim arr
 6202     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000010/imm32"    "F - test-convert-index-into-array-on-stack/13")
 6203     #
 6204     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-on-stack/14")
 6205     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-on-stack/15")
 6206     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-on-stack/16")
 6207     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-on-stack/17")
 6208     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-on-stack/18")
 6209     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-on-stack/19")
 6210     # . epilogue
 6211     89/<- %esp 5/r32/ebp
 6212     5d/pop-to-ebp
 6213     c3/return
 6214 
 6215 test-convert-index-into-array-on-stack-with-literal:
 6216     # . prologue
 6217     55/push-ebp
 6218     89/<- %ebp 4/r32/esp
 6219     # setup
 6220     (clear-stream _test-input-stream)
 6221     (clear-stream $_test-input-buffered-file->buffer)
 6222     (clear-stream _test-output-stream)
 6223     (clear-stream $_test-output-buffered-file->buffer)
 6224     #
 6225     (write _test-input-stream "fn foo {\n")
 6226     (write _test-input-stream "  var arr: (array int 3)\n")
 6227     (write _test-input-stream "  var x/eax: (addr int) <- index arr, 2\n")
 6228     (write _test-input-stream "}\n")
 6229     # convert
 6230     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6231     (flush _test-output-buffered-file)
 6232 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6238     # check output
 6239     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-on-stack-with-literal/0")
 6240     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-on-stack-with-literal/1")
 6241     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-on-stack-with-literal/2")
 6242     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-on-stack-with-literal/3")
 6243     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-on-stack-with-literal/4")
 6244     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-on-stack-with-literal/5")
 6245     # var arr
 6246     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"          "F - test-convert-index-into-array-on-stack-with-literal/6")
 6247     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"                "F - test-convert-index-into-array-on-stack-with-literal/7")
 6248     # var x
 6249     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-on-stack-with-literal/8")
 6250     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds 2 0x00000004 *(ebp+0xfffffff0) \"foo\" \"arr\")"  "F - test-convert-index-into-array-on-stack-with-literal/9")
 6251     # x is at (ebp-0x10) + 4 + 2*4 = ebp-4
 6252     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp + 0xfffffffc) 0x00000000/r32"  "F - test-convert-index-into-array-on-stack-with-literal/10")
 6253     # reclaim x
 6254     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-on-stack-with-literal/11")
 6255     # reclaim arr
 6256     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000010/imm32"    "F - test-convert-index-into-array-on-stack-with-literal/12")
 6257     #
 6258     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-on-stack-with-literal/13")
 6259     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-on-stack-with-literal/14")
 6260     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-on-stack-with-literal/15")
 6261     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-on-stack-with-literal/16")
 6262     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-on-stack-with-literal/17")
 6263     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-on-stack-with-literal/18")
 6264     # . epilogue
 6265     89/<- %esp 5/r32/ebp
 6266     5d/pop-to-ebp
 6267     c3/return
 6268 
 6269 test-convert-index-into-array-of-bytes-on-stack-with-literal:
 6270     # . prologue
 6271     55/push-ebp
 6272     89/<- %ebp 4/r32/esp
 6273     # setup
 6274     (clear-stream _test-input-stream)
 6275     (clear-stream $_test-input-buffered-file->buffer)
 6276     (clear-stream _test-output-stream)
 6277     (clear-stream $_test-output-buffered-file->buffer)
 6278     #
 6279     (write _test-input-stream "fn foo {\n")
 6280     (write _test-input-stream "  var arr: (array byte 3)\n")
 6281     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, 2\n")
 6282     (write _test-input-stream "}\n")
 6283     # convert
 6284     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6285     (flush _test-output-buffered-file)
 6286 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6292     # check output
 6293     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/0")
 6294     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/1")
 6295     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/2")
 6296     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/3")
 6297     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/4")
 6298     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/5")
 6299     # var arr
 6300     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x00000003)"          "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/6")
 6301     (check-next-stream-line-equal _test-output-stream "    68/push 0x00000003/imm32"                "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/7")
 6302     # var x
 6303     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/8")
 6304     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds 2 0x00000001 *(ebp+0xfffffff9) \"foo\" \"arr\")"  "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/9")
 6305     # x is at (ebp-7) + 4 + 2 = ebp-1
 6306     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp + 0xffffffff) 0x00000000/r32"  "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/10")
 6307     # reclaim x
 6308     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/11")
 6309     # reclaim arr
 6310     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000007/imm32"    "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/12")
 6311     #
 6312     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/13")
 6313     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/14")
 6314     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/15")
 6315     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/16")
 6316     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/17")
 6317     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/18")
 6318     # . epilogue
 6319     89/<- %esp 5/r32/ebp
 6320     5d/pop-to-ebp
 6321     c3/return
 6322 
 6323 test-convert-index-into-array-using-offset:
 6324     # . prologue
 6325     55/push-ebp
 6326     89/<- %ebp 4/r32/esp
 6327     # setup
 6328     (clear-stream _test-input-stream)
 6329     (clear-stream $_test-input-buffered-file->buffer)
 6330     (clear-stream _test-output-stream)
 6331     (clear-stream $_test-output-buffered-file->buffer)
 6332     #
 6333     (write _test-input-stream "fn foo {\n")
 6334     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
 6335     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 6336     (write _test-input-stream "  var off/ecx: (offset int) <- compute-offset arr, idx\n")
 6337     (write _test-input-stream "  var x/eax: (addr int) <- index arr, off\n")
 6338     (write _test-input-stream "}\n")
 6339     # convert
 6340     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6341     (flush _test-output-buffered-file)
 6342 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6348     # check output
 6349     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-using-offset/0")
 6350     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-using-offset/1")
 6351     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-using-offset/2")
 6352     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-using-offset/3")
 6353     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-using-offset/4")
 6354     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-using-offset/5")
 6355     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-using-offset/6")
 6356     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-using-offset/7")
 6357     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-using-offset/8")
 6358     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-index-into-array-using-offset/9")
 6359     (check-next-stream-line-equal _test-output-stream "    69/multiply %ecx 0x00000004/imm32 0x00000001/r32"  "F - test-convert-index-into-array-using-offset/10")
 6360     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds %ecx 1 *eax \"foo\" \"arr\")"  "F - test-convert-index-into-array-using-offset/11")
 6361     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx + 4) 0x00000000/r32"  "F - test-convert-index-into-array-using-offset/12")
 6362     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-using-offset/13")
 6363     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-using-offset/14")
 6364     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-using-offset/15")
 6365     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-using-offset/16")
 6366     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-using-offset/17")
 6367     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-using-offset/18")
 6368     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-using-offset/19")
 6369     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-using-offset/20")
 6370     # . epilogue
 6371     89/<- %esp 5/r32/ebp
 6372     5d/pop-to-ebp
 6373     c3/return
 6374 
 6375 test-convert-index-into-array-of-bytes-using-offset:
 6376     # . prologue
 6377     55/push-ebp
 6378     89/<- %ebp 4/r32/esp
 6379     # setup
 6380     (clear-stream _test-input-stream)
 6381     (clear-stream $_test-input-buffered-file->buffer)
 6382     (clear-stream _test-output-stream)
 6383     (clear-stream $_test-output-buffered-file->buffer)
 6384     #
 6385     (write _test-input-stream "fn foo {\n")
 6386     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
 6387     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 6388     (write _test-input-stream "  var off/ecx: (offset byte) <- compute-offset arr, idx\n")
 6389     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, off\n")
 6390     (write _test-input-stream "}\n")
 6391     # convert
 6392     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6393     (flush _test-output-buffered-file)
 6394 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6400     # check output
 6401     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-using-offset/0")
 6402     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-using-offset/1")
 6403     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-using-offset/2")
 6404     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-of-bytes-using-offset/3")
 6405     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-using-offset/4")
 6406     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-using-offset/5")
 6407     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-of-bytes-using-offset/6")
 6408     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-of-bytes-using-offset/7")
 6409     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-of-bytes-using-offset/8")
 6410     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-index-into-array-of-bytes-using-offset/9")
 6411     (check-next-stream-line-equal _test-output-stream "    69/multiply %ecx 0x00000001/imm32 0x00000001/r32"  "F - test-convert-index-into-array-of-bytes-using-offset/10")
 6412     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds %ecx 1 *eax \"foo\" \"arr\")"  "F - test-convert-index-into-array-of-bytes-using-offset/11")
 6413     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx + 4) 0x00000000/r32"  "F - test-convert-index-into-array-of-bytes-using-offset/12")
 6414     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-of-bytes-using-offset/13")
 6415     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes-using-offset/14")
 6416     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-using-offset/15")
 6417     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-using-offset/16")
 6418     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-using-offset/17")
 6419     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes-using-offset/18")
 6420     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes-using-offset/19")
 6421     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-using-offset/20")
 6422     # . epilogue
 6423     89/<- %esp 5/r32/ebp
 6424     5d/pop-to-ebp
 6425     c3/return
 6426 
 6427 test-convert-index-into-array-using-offset-on-stack:
 6428     # . prologue
 6429     55/push-ebp
 6430     89/<- %ebp 4/r32/esp
 6431     # setup
 6432     (clear-stream _test-input-stream)
 6433     (clear-stream $_test-input-buffered-file->buffer)
 6434     (clear-stream _test-output-stream)
 6435     (clear-stream $_test-output-buffered-file->buffer)
 6436     #
 6437     (write _test-input-stream "fn foo {\n")
 6438     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
 6439     (write _test-input-stream "  var idx: int\n")
 6440     (write _test-input-stream "  var off/ecx: (offset int) <- compute-offset arr, idx\n")
 6441     (write _test-input-stream "  var x/eax: (addr int) <- index arr, off\n")
 6442     (write _test-input-stream "}\n")
 6443     # convert
 6444     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6445     (flush _test-output-buffered-file)
 6446 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6452     # check output
 6453     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-using-offset-on-stack/0")
 6454     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-using-offset-on-stack/1")
 6455     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-using-offset-on-stack/2")
 6456     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-using-offset-on-stack/3")
 6457     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-using-offset-on-stack/4")
 6458     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-using-offset-on-stack/5")
 6459     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-using-offset-on-stack/6")
 6460     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-using-offset-on-stack/7")
 6461     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"                         "F - test-convert-index-into-array-using-offset-on-stack/8")
 6462     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-using-offset-on-stack/9")
 6463     (check-next-stream-line-equal _test-output-stream "    69/multiply *(ebp+0xfffffff8) 0x00000004/imm32 0x00000001/r32"  "F - test-convert-index-into-array-using-offset-on-stack/10")
 6464     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds %ecx 1 *eax \"foo\" \"arr\")"  "F - test-convert-index-into-array-using-offset-on-stack/11")
 6465     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx + 4) 0x00000000/r32"  "F - test-convert-index-into-array-using-offset-on-stack/12")
 6466     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-using-offset-on-stack/13")
 6467     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"    "F - test-convert-index-into-array-using-offset-on-stack/14")
 6468     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-using-offset-on-stack/15")
 6469     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-using-offset-on-stack/16")
 6470     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-using-offset-on-stack/17")
 6471     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-using-offset-on-stack/18")
 6472     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-using-offset-on-stack/19")
 6473     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-using-offset-on-stack/20")
 6474     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-using-offset-on-stack/21")
 6475     # . epilogue
 6476     89/<- %esp 5/r32/ebp
 6477     5d/pop-to-ebp
 6478     c3/return
 6479 
 6480 test-convert-index-into-array-of-bytes-using-offset-on-stack:
 6481     # . prologue
 6482     55/push-ebp
 6483     89/<- %ebp 4/r32/esp
 6484     # setup
 6485     (clear-stream _test-input-stream)
 6486     (clear-stream $_test-input-buffered-file->buffer)
 6487     (clear-stream _test-output-stream)
 6488     (clear-stream $_test-output-buffered-file->buffer)
 6489     #
 6490     (write _test-input-stream "fn foo {\n")
 6491     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
 6492     (write _test-input-stream "  var idx: int\n")
 6493     (write _test-input-stream "  var off/ecx: (offset byte) <- compute-offset arr, idx\n")
 6494     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, off\n")
 6495     (write _test-input-stream "}\n")
 6496     # convert
 6497     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6498     (flush _test-output-buffered-file)
 6499 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6505     # check output
 6506     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/0")
 6507     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/1")
 6508     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/2")
 6509     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/3")
 6510     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/4")
 6511     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/5")
 6512     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/6")
 6513     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/7")
 6514     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"                         "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/8")
 6515     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/9")
 6516     (check-next-stream-line-equal _test-output-stream "    69/multiply *(ebp+0xfffffff8) 0x00000001/imm32 0x00000001/r32"  "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/10")
 6517     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds %ecx 1 *eax \"foo\" \"arr\")"  "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/11")
 6518     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx + 4) 0x00000000/r32"  "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/12")
 6519     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/13")
 6520     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"    "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/14")
 6521     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/15")
 6522     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/16")
 6523     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/17")
 6524     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/18")
 6525     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/19")
 6526     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/20")
 6527     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/21")
 6528     # . epilogue
 6529     89/<- %esp 5/r32/ebp
 6530     5d/pop-to-ebp
 6531     c3/return
 6532 
 6533 test-convert-function-and-type-definition:
 6534     # . prologue
 6535     55/push-ebp
 6536     89/<- %ebp 4/r32/esp
 6537     # setup
 6538     (clear-stream _test-input-stream)
 6539     (clear-stream $_test-input-buffered-file->buffer)
 6540     (clear-stream _test-output-stream)
 6541     (clear-stream $_test-output-buffered-file->buffer)
 6542     #
 6543     (write _test-input-stream "fn foo a: (addr t) {\n")
 6544     (write _test-input-stream "  var _a/eax: (addr t) <- copy a\n")
 6545     (write _test-input-stream "  var b/ecx: (addr int) <- get _a, x\n")
 6546     (write _test-input-stream "  var c/ecx: (addr int) <- get _a, y\n")
 6547     (write _test-input-stream "}\n")
 6548     (write _test-input-stream "type t {\n")
 6549     (write _test-input-stream "  x: int\n")
 6550     (write _test-input-stream "  y: int\n")
 6551     (write _test-input-stream "}\n")
 6552     # convert
 6553     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6554     (flush _test-output-buffered-file)
 6555 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6561     # check output
 6562     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-and-type-definition/0")
 6563     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-and-type-definition/1")
 6564     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-and-type-definition/2")
 6565     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-and-type-definition/3")
 6566     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-and-type-definition/4")
 6567     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-and-type-definition/5")
 6568     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-and-type-definition/6")
 6569     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-function-and-type-definition/7")
 6570     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-and-type-definition/8")
 6571     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + 0x00000000) 0x00000001/r32"  "F - test-convert-function-and-type-definition/9")
 6572     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + 0x00000004) 0x00000001/r32"  "F - test-convert-function-and-type-definition/11")
 6573     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-and-type-definition/13")
 6574     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-function-and-type-definition/14")
 6575     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-and-type-definition/15")
 6576     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-and-type-definition/16")
 6577     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-and-type-definition/17")
 6578     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-and-type-definition/18")
 6579     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-and-type-definition/19")
 6580     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-and-type-definition/20")
 6581     # . epilogue
 6582     89/<- %esp 5/r32/ebp
 6583     5d/pop-to-ebp
 6584     c3/return
 6585 
 6586 test-type-definition-with-array:
 6587     # . prologue
 6588     55/push-ebp
 6589     89/<- %ebp 4/r32/esp
 6590     # setup
 6591     (clear-stream _test-input-stream)
 6592     (clear-stream $_test-input-buffered-file->buffer)
 6593     (clear-stream _test-output-stream)
 6594     (clear-stream $_test-output-buffered-file->buffer)
 6595     (clear-stream _test-error-stream)
 6596     (clear-stream $_test-error-buffered-file->buffer)
 6597     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6598     68/push 0/imm32
 6599     68/push 0/imm32
 6600     89/<- %edx 4/r32/esp
 6601     (tailor-exit-descriptor %edx 0x10)
 6602     #
 6603     (write _test-input-stream "type t {\n")
 6604     (write _test-input-stream "  a: (array int 3)\n")
 6605     (write _test-input-stream "}\n")
 6606     # convert
 6607     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6608     # registers except esp clobbered at this point
 6609     # restore ed
 6610     89/<- %edx 4/r32/esp
 6611     (flush _test-output-buffered-file)
 6612     (flush _test-error-buffered-file)
 6613 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6619     # check output
 6620     (check-stream-equal _test-output-stream  ""  "F - test-type-definition-with-array: output should be empty")
 6621     (check-next-stream-line-equal _test-error-stream  "type t: 'array' elements not allowed for now"  "F - test-type-definition-with-array: error message")
 6622     # check that stop(1) was called
 6623     (check-ints-equal *(edx+4) 2 "F - test-type-definition-with-array: exit status")
 6624     # don't restore from ebp
 6625     81 0/subop/add %esp 8/imm32
 6626     # . epilogue
 6627     5d/pop-to-ebp
 6628     c3/return
 6629 
 6630 test-type-definition-with-addr:
 6631     # . prologue
 6632     55/push-ebp
 6633     89/<- %ebp 4/r32/esp
 6634     # setup
 6635     (clear-stream _test-input-stream)
 6636     (clear-stream $_test-input-buffered-file->buffer)
 6637     (clear-stream _test-output-stream)
 6638     (clear-stream $_test-output-buffered-file->buffer)
 6639     (clear-stream _test-error-stream)
 6640     (clear-stream $_test-error-buffered-file->buffer)
 6641     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 6642     68/push 0/imm32
 6643     68/push 0/imm32
 6644     89/<- %edx 4/r32/esp
 6645     (tailor-exit-descriptor %edx 0x10)
 6646     #
 6647     (write _test-input-stream "type t {\n")
 6648     (write _test-input-stream "  a: (addr int)\n")
 6649     (write _test-input-stream "}\n")
 6650     # convert
 6651     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 6652     # registers except esp clobbered at this point
 6653     # restore ed
 6654     89/<- %edx 4/r32/esp
 6655     (flush _test-output-buffered-file)
 6656     (flush _test-error-buffered-file)
 6657 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6663     # check output
 6664     (check-stream-equal _test-output-stream  ""  "F - test-type-definition-with-addr: output should be empty")
 6665     (check-next-stream-line-equal _test-error-stream  "type t: 'addr' elements not allowed"  "F - test-type-definition-with-addr: error message")
 6666     # check that stop(1) was called
 6667     (check-ints-equal *(edx+4) 2 "F - test-type-definition-with-addr: exit status")
 6668     # don't restore from ebp
 6669     81 0/subop/add %esp 8/imm32
 6670     # . epilogue
 6671     5d/pop-to-ebp
 6672     c3/return
 6673 
 6674 test-convert-function-with-local-var-with-user-defined-type:
 6675     # . prologue
 6676     55/push-ebp
 6677     89/<- %ebp 4/r32/esp
 6678     # setup
 6679     (clear-stream _test-input-stream)
 6680     (clear-stream $_test-input-buffered-file->buffer)
 6681     (clear-stream _test-output-stream)
 6682     (clear-stream $_test-output-buffered-file->buffer)
 6683     #
 6684     (write _test-input-stream "fn foo {\n")
 6685     (write _test-input-stream "  var a: t\n")
 6686     (write _test-input-stream "}\n")
 6687     (write _test-input-stream "type t {\n")
 6688     (write _test-input-stream "  x: int\n")
 6689     (write _test-input-stream "  y: int\n")
 6690     (write _test-input-stream "}\n")
 6691     # convert
 6692     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6693     (flush _test-output-buffered-file)
 6694 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6700     # check output
 6701     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-with-user-defined-type/0")
 6702     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-with-user-defined-type/1")
 6703     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-with-user-defined-type/2")
 6704     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-with-user-defined-type/3")
 6705     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-with-user-defined-type/4")
 6706     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-with-user-defined-type/5")
 6707     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-with-user-defined-type/6")
 6708     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-with-user-defined-type/7")
 6709     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000008/imm32"  "F - test-convert-function-with-local-var-with-user-defined-type/8")
 6710     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-with-user-defined-type/9")
 6711     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-with-user-defined-type/10")
 6712     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-with-user-defined-type/11")
 6713     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-with-user-defined-type/12")
 6714     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-with-user-defined-type/13")
 6715     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-with-user-defined-type/14")
 6716     # . epilogue
 6717     89/<- %esp 5/r32/ebp
 6718     5d/pop-to-ebp
 6719     c3/return
 6720 
 6721 test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type:
 6722     # . prologue
 6723     55/push-ebp
 6724     89/<- %ebp 4/r32/esp
 6725     # setup
 6726     (clear-stream _test-input-stream)
 6727     (clear-stream $_test-input-buffered-file->buffer)
 6728     (clear-stream _test-output-stream)
 6729     (clear-stream $_test-output-buffered-file->buffer)
 6730     #
 6731     (write _test-input-stream "fn foo {\n")
 6732     (write _test-input-stream "  var a: t\n")
 6733     (write _test-input-stream "}\n")
 6734     (write _test-input-stream "type t {\n")
 6735     (write _test-input-stream "  x: s\n")
 6736     (write _test-input-stream "}\n")
 6737     (write _test-input-stream "type s {\n")
 6738     (write _test-input-stream "  z: int\n")
 6739     (write _test-input-stream "}\n")
 6740     # convert
 6741     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6742     (flush _test-output-buffered-file)
 6743 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6749     # check output
 6750     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/0")
 6751     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/1")
 6752     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/2")
 6753     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/3")
 6754     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/4")
 6755     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/5")
 6756     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/7")
 6757     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/8")
 6758     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/9")
 6759     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/10")
 6760     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/11")
 6761     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/12")
 6762     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/13")
 6763     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/14")
 6764     # . epilogue
 6765     89/<- %esp 5/r32/ebp
 6766     5d/pop-to-ebp
 6767     c3/return
 6768 
 6769 test-convert-function-call-with-arg-of-user-defined-type:
 6770     # . prologue
 6771     55/push-ebp
 6772     89/<- %ebp 4/r32/esp
 6773     # setup
 6774     (clear-stream _test-input-stream)
 6775     (clear-stream $_test-input-buffered-file->buffer)
 6776     (clear-stream _test-output-stream)
 6777     (clear-stream $_test-output-buffered-file->buffer)
 6778     #
 6779     (write _test-input-stream "fn f {\n")
 6780     (write _test-input-stream "  var a: t\n")
 6781     (write _test-input-stream "  foo a\n")
 6782     (write _test-input-stream "}\n")
 6783     (write _test-input-stream "fn foo x: t {\n")
 6784     (write _test-input-stream "}\n")
 6785     (write _test-input-stream "type t {\n")
 6786     (write _test-input-stream "  x: int\n")
 6787     (write _test-input-stream "  y: int\n")
 6788     (write _test-input-stream "}\n")
 6789     # convert
 6790     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6791     (flush _test-output-buffered-file)
 6792 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6798     # check output
 6799     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-arg-of-user-defined-type/0")
 6800     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/1")
 6801     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/2")
 6802     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-arg-of-user-defined-type/3")
 6803     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type/4")
 6804     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"     "F - test-convert-function-call-with-arg-of-user-defined-type/5")
 6805     # var a: t
 6806     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-call-with-arg-of-user-defined-type/6")
 6807     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-call-with-arg-of-user-defined-type/7")
 6808     # foo a
 6809     (check-next-stream-line-equal _test-output-stream "    (foo *(ebp+0xfffffff8) *(ebp+0xfffffffc))"  "F - test-convert-function-call-with-arg-of-user-defined-type/8")
 6810     #
 6811     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000008/imm32"  "F - test-convert-function-call-with-arg-of-user-defined-type/9")
 6812     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type/10")
 6813     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"    "F - test-convert-function-call-with-arg-of-user-defined-type/11")
 6814     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/12")
 6815     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-arg-of-user-defined-type/13")
 6816     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/14")
 6817     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/15")
 6818     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call-with-arg-of-user-defined-type/16")
 6819     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/17")
 6820     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/18")
 6821     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-arg-of-user-defined-type/19")
 6822     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/20")
 6823     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-arg-of-user-defined-type/21")
 6824     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/22")
 6825     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/23")
 6826     # . epilogue
 6827     89/<- %esp 5/r32/ebp
 6828     5d/pop-to-ebp
 6829     c3/return
 6830 
 6831 test-convert-function-call-with-arg-of-user-defined-type-register-indirect:
 6832     # . prologue
 6833     55/push-ebp
 6834     89/<- %ebp 4/r32/esp
 6835     # setup
 6836     (clear-stream _test-input-stream)
 6837     (clear-stream $_test-input-buffered-file->buffer)
 6838     (clear-stream _test-output-stream)
 6839     (clear-stream $_test-output-buffered-file->buffer)
 6840     #
 6841     (write _test-input-stream "fn f {\n")
 6842     (write _test-input-stream "  var a/eax: (addr t) <- copy 0\n")
 6843     (write _test-input-stream "  foo *a\n")
 6844     (write _test-input-stream "}\n")
 6845     (write _test-input-stream "fn foo x: t {\n")
 6846     (write _test-input-stream "}\n")
 6847     (write _test-input-stream "type t {\n")
 6848     (write _test-input-stream "  x: int\n")
 6849     (write _test-input-stream "  y: int\n")
 6850     (write _test-input-stream "}\n")
 6851     # convert
 6852     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6853     (flush _test-output-buffered-file)
 6854 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6860     # check output
 6861     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-arg-of-user-defined-type/0")
 6862     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/1")
 6863     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/2")
 6864     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-arg-of-user-defined-type/3")
 6865     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type/4")
 6866     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"     "F - test-convert-function-call-with-arg-of-user-defined-type/5")
 6867     # var a
 6868     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-call-with-arg-of-user-defined-type/6")
 6869     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"  "F - test-convert-function-call-with-arg-of-user-defined-type/7")
 6870     # foo a
 6871     (check-next-stream-line-equal _test-output-stream "    (foo *(eax+0x00000000) *(eax+0x00000004))"  "F - test-convert-function-call-with-arg-of-user-defined-type/8")
 6872     #
 6873     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-function-call-with-arg-of-user-defined-type/9")
 6874     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type/10")
 6875     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"    "F - test-convert-function-call-with-arg-of-user-defined-type/11")
 6876     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/12")
 6877     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-arg-of-user-defined-type/13")
 6878     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/14")
 6879     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/15")
 6880     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call-with-arg-of-user-defined-type/16")
 6881     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/17")
 6882     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/18")
 6883     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-arg-of-user-defined-type/19")
 6884     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/20")
 6885     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-arg-of-user-defined-type/21")
 6886     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/22")
 6887     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/23")
 6888     # . epilogue
 6889     89/<- %esp 5/r32/ebp
 6890     5d/pop-to-ebp
 6891     c3/return
 6892 
 6893 # we don't have special support for call-by-reference; just explicitly create
 6894 # a new variable with the address of the arg
 6895 test-convert-function-call-with-arg-of-user-defined-type-by-reference:
 6896     # . prologue
 6897     55/push-ebp
 6898     89/<- %ebp 4/r32/esp
 6899     # setup
 6900     (clear-stream _test-input-stream)
 6901     (clear-stream $_test-input-buffered-file->buffer)
 6902     (clear-stream _test-output-stream)
 6903     (clear-stream $_test-output-buffered-file->buffer)
 6904     #
 6905     (write _test-input-stream "fn f {\n")
 6906     (write _test-input-stream "  var a: t\n")
 6907     (write _test-input-stream "  var b/eax: (addr t) <- address a\n")
 6908     (write _test-input-stream "  foo b\n")
 6909     (write _test-input-stream "}\n")
 6910     (write _test-input-stream "fn foo x: (addr t) {\n")
 6911     (write _test-input-stream "  var x/ecx: (addr t) <- copy x\n")
 6912     (write _test-input-stream "}\n")
 6913     (write _test-input-stream "type t {\n")
 6914     (write _test-input-stream "  x: int\n")
 6915     (write _test-input-stream "  y: int\n")
 6916     (write _test-input-stream "}\n")
 6917     # convert
 6918     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6919     (flush _test-output-buffered-file)
 6920 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6926     # check output
 6927     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/0")
 6928     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/1")
 6929     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/2")
 6930     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/3")
 6931     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/4")
 6932     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/5")
 6933     # var a: t
 6934     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/6")
 6935     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/7")
 6936     # var b/eax: (addr t)
 6937     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/8")
 6938     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp+0xfffffff8) 0x00000000/r32"  "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/9")
 6939     # foo a
 6940     (check-next-stream-line-equal _test-output-stream "    (foo %eax)"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/10")
 6941     #
 6942     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/11")
 6943     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000008/imm32"  "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/12")
 6944     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/13")
 6945     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"    "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/14")
 6946     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/15")
 6947     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/16")
 6948     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/17")
 6949     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/18")
 6950     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/19")
 6951     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/20")
 6952     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/21")
 6953     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/22")
 6954     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/23")
 6955     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/24")
 6956     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/25")
 6957     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000001/r32"  "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/26")
 6958     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/27")
 6959     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/28")
 6960     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/29")
 6961     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/30")
 6962     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/31")
 6963     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/32")
 6964     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/33")
 6965     # . epilogue
 6966     89/<- %esp 5/r32/ebp
 6967     5d/pop-to-ebp
 6968     c3/return
 6969 
 6970 test-convert-get-on-local-variable:
 6971     # . prologue
 6972     55/push-ebp
 6973     89/<- %ebp 4/r32/esp
 6974     # setup
 6975     (clear-stream _test-input-stream)
 6976     (clear-stream $_test-input-buffered-file->buffer)
 6977     (clear-stream _test-output-stream)
 6978     (clear-stream $_test-output-buffered-file->buffer)
 6979     #
 6980     (write _test-input-stream "fn foo {\n")
 6981     (write _test-input-stream "  var a: t\n")
 6982     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 6983     (write _test-input-stream "}\n")
 6984     (write _test-input-stream "type t {\n")
 6985     (write _test-input-stream "  x: int\n")
 6986     (write _test-input-stream "  y: int\n")
 6987     (write _test-input-stream "}\n")
 6988     # convert
 6989     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 6990     (flush _test-output-buffered-file)
 6991 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 6997     # check output
 6998     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-get-on-local-variable/0")
 6999     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-get-on-local-variable/1")
 7000     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-get-on-local-variable/2")
 7001     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-get-on-local-variable/3")
 7002     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-get-on-local-variable/4")
 7003     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-get-on-local-variable/5")
 7004     # var a
 7005     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-get-on-local-variable/6")
 7006     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-get-on-local-variable/7")
 7007     # var c
 7008     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-get-on-local-variable/8")
 7009     # get
 7010     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp+0xfffffffc) 0x00000001/r32"  "F - test-convert-get-on-local-variable/9")
 7011     # reclaim c
 7012     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-get-on-local-variable/10")
 7013     # reclaim a
 7014     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000008/imm32"  "F - test-convert-get-on-local-variable/11")
 7015     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-get-on-local-variable/12")
 7016     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-get-on-local-variable/13")
 7017     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-get-on-local-variable/14")
 7018     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-get-on-local-variable/15")
 7019     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-get-on-local-variable/16")
 7020     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-get-on-local-variable/17")
 7021     # . epilogue
 7022     89/<- %esp 5/r32/ebp
 7023     5d/pop-to-ebp
 7024     c3/return
 7025 
 7026 test-convert-get-on-function-argument:
 7027     # . prologue
 7028     55/push-ebp
 7029     89/<- %ebp 4/r32/esp
 7030     # setup
 7031     (clear-stream _test-input-stream)
 7032     (clear-stream $_test-input-buffered-file->buffer)
 7033     (clear-stream _test-output-stream)
 7034     (clear-stream $_test-output-buffered-file->buffer)
 7035     #
 7036     (write _test-input-stream "fn foo a: t {\n")
 7037     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 7038     (write _test-input-stream "}\n")
 7039     (write _test-input-stream "type t {\n")
 7040     (write _test-input-stream "  x: int\n")
 7041     (write _test-input-stream "  y: int\n")
 7042     (write _test-input-stream "}\n")
 7043     # convert
 7044     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7045     (flush _test-output-buffered-file)
 7046 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7052     # check output
 7053     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-get-on-function-argument/0")
 7054     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-get-on-function-argument/1")
 7055     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-get-on-function-argument/2")
 7056     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-get-on-function-argument/3")
 7057     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-get-on-function-argument/4")
 7058     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-get-on-function-argument/5")
 7059     # var c
 7060     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-get-on-function-argument/6")
 7061     # get
 7062     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp+0x0000000c) 0x00000001/r32"  "F - test-convert-get-on-function-argument/7")
 7063     # reclaim c
 7064     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-get-on-function-argument/8")
 7065     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-get-on-function-argument/9")
 7066     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-get-on-function-argument/10")
 7067     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-get-on-function-argument/11")
 7068     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-get-on-function-argument/12")
 7069     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-get-on-function-argument/13")
 7070     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-get-on-function-argument/14")
 7071     # . epilogue
 7072     89/<- %esp 5/r32/ebp
 7073     5d/pop-to-ebp
 7074     c3/return
 7075 
 7076 test-convert-get-on-function-argument-with-known-type:
 7077     # . prologue
 7078     55/push-ebp
 7079     89/<- %ebp 4/r32/esp
 7080     # setup
 7081     (clear-stream _test-input-stream)
 7082     (clear-stream $_test-input-buffered-file->buffer)
 7083     (clear-stream _test-output-stream)
 7084     (clear-stream $_test-output-buffered-file->buffer)
 7085     #
 7086     (write _test-input-stream "type t {\n")
 7087     (write _test-input-stream "  x: int\n")
 7088     (write _test-input-stream "  y: int\n")
 7089     (write _test-input-stream "}\n")
 7090     (write _test-input-stream "fn foo a: t {\n")
 7091     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 7092     (write _test-input-stream "}\n")
 7093     # convert
 7094     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7095     (flush _test-output-buffered-file)
 7096 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7102     # check output
 7103     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-get-on-function-argument-with-known-type/0")
 7104     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-get-on-function-argument-with-known-type/1")
 7105     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-get-on-function-argument-with-known-type/2")
 7106     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-get-on-function-argument-with-known-type/3")
 7107     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-get-on-function-argument-with-known-type/4")
 7108     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-get-on-function-argument-with-known-type/5")
 7109     # var c
 7110     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-get-on-function-argument-with-known-type/6")
 7111     # get
 7112     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp+0x0000000c) 0x00000001/r32"  "F - test-convert-get-on-function-argument-with-known-type/7")
 7113     # reclaim c
 7114     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-get-on-function-argument-with-known-type/8")
 7115     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-get-on-function-argument-with-known-type/9")
 7116     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-get-on-function-argument-with-known-type/10")
 7117     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-get-on-function-argument-with-known-type/11")
 7118     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-get-on-function-argument-with-known-type/12")
 7119     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-get-on-function-argument-with-known-type/13")
 7120     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-get-on-function-argument-with-known-type/14")
 7121     # . epilogue
 7122     89/<- %esp 5/r32/ebp
 7123     5d/pop-to-ebp
 7124     c3/return
 7125 
 7126 test-add-with-too-many-inouts:
 7127     # . prologue
 7128     55/push-ebp
 7129     89/<- %ebp 4/r32/esp
 7130     # setup
 7131     (clear-stream _test-input-stream)
 7132     (clear-stream $_test-input-buffered-file->buffer)
 7133     (clear-stream _test-output-stream)
 7134     (clear-stream $_test-output-buffered-file->buffer)
 7135     (clear-stream _test-error-stream)
 7136     (clear-stream $_test-error-buffered-file->buffer)
 7137     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7138     68/push 0/imm32
 7139     68/push 0/imm32
 7140     89/<- %edx 4/r32/esp
 7141     (tailor-exit-descriptor %edx 0x10)
 7142     #
 7143     (write _test-input-stream "fn foo {\n")
 7144     (write _test-input-stream "  var a: int\n")
 7145     (write _test-input-stream "  var b/ecx: int <- add a, 0\n")
 7146     (write _test-input-stream "}\n")
 7147     # convert
 7148     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7149     # registers except esp clobbered at this point
 7150     # restore ed
 7151     89/<- %edx 4/r32/esp
 7152     (flush _test-output-buffered-file)
 7153     (flush _test-error-buffered-file)
 7154 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7160     # check output
 7161     (check-stream-equal _test-output-stream  ""  "F - test-add-with-too-many-inouts: output should be empty")
 7162     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt add: too many inouts; most primitives support at most two arguments, across inouts and outputs"  "F - test-add-with-too-many-inouts: error message")
 7163     # check that stop(1) was called
 7164     (check-ints-equal *(edx+4) 2 "F - test-add-with-too-many-inouts: exit status")
 7165     # don't restore from ebp
 7166     81 0/subop/add %esp 8/imm32
 7167     # . epilogue
 7168     5d/pop-to-ebp
 7169     c3/return
 7170 
 7171 test-add-with-too-many-inouts-2:
 7172     # . prologue
 7173     55/push-ebp
 7174     89/<- %ebp 4/r32/esp
 7175     # setup
 7176     (clear-stream _test-input-stream)
 7177     (clear-stream $_test-input-buffered-file->buffer)
 7178     (clear-stream _test-output-stream)
 7179     (clear-stream $_test-output-buffered-file->buffer)
 7180     (clear-stream _test-error-stream)
 7181     (clear-stream $_test-error-buffered-file->buffer)
 7182     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7183     68/push 0/imm32
 7184     68/push 0/imm32
 7185     89/<- %edx 4/r32/esp
 7186     (tailor-exit-descriptor %edx 0x10)
 7187     #
 7188     (write _test-input-stream "fn foo {\n")
 7189     (write _test-input-stream "  var a: int\n")
 7190     (write _test-input-stream "  add-to a, 0, 1\n")
 7191     (write _test-input-stream "}\n")
 7192     # convert
 7193     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7194     # registers except esp clobbered at this point
 7195     # restore ed
 7196     89/<- %edx 4/r32/esp
 7197     (flush _test-output-buffered-file)
 7198     (flush _test-error-buffered-file)
 7199 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7205     # check output
 7206     (check-stream-equal _test-output-stream  ""  "F - test-add-with-too-many-inouts-2: output should be empty")
 7207     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt add-to: too many inouts; most primitives support at most two arguments, across inouts and outputs"  "F - test-add-with-too-many-inouts-2: error message")
 7208     # check that stop(1) was called
 7209     (check-ints-equal *(edx+4) 2 "F - test-add-with-too-many-inouts-2: exit status")
 7210     # don't restore from ebp
 7211     81 0/subop/add %esp 8/imm32
 7212     # . epilogue
 7213     5d/pop-to-ebp
 7214     c3/return
 7215 
 7216 test-add-with-too-many-outputs:
 7217     # . prologue
 7218     55/push-ebp
 7219     89/<- %ebp 4/r32/esp
 7220     # setup
 7221     (clear-stream _test-input-stream)
 7222     (clear-stream $_test-input-buffered-file->buffer)
 7223     (clear-stream _test-output-stream)
 7224     (clear-stream $_test-output-buffered-file->buffer)
 7225     (clear-stream _test-error-stream)
 7226     (clear-stream $_test-error-buffered-file->buffer)
 7227     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7228     68/push 0/imm32
 7229     68/push 0/imm32
 7230     89/<- %edx 4/r32/esp
 7231     (tailor-exit-descriptor %edx 0x10)
 7232     #
 7233     (write _test-input-stream "fn foo {\n")
 7234     (write _test-input-stream "  var a/eax: int <- copy 0\n")
 7235     (write _test-input-stream "  var b/ebx: int <- copy 0\n")
 7236     (write _test-input-stream "  var c/ecx: int <- copy 0\n")
 7237     (write _test-input-stream "  c, b <- add a\n")
 7238     (write _test-input-stream "}\n")
 7239     # convert
 7240     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7241     # registers except esp clobbered at this point
 7242     # restore ed
 7243     89/<- %edx 4/r32/esp
 7244     (flush _test-output-buffered-file)
 7245     (flush _test-error-buffered-file)
 7246 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7252     # check output
 7253     (check-stream-equal _test-output-stream  ""  "F - test-add-with-too-many-outputs: output should be empty")
 7254     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt add: too many outputs; most primitives support at most one output"  "F - test-add-with-too-many-outputs: error message")
 7255     # check that stop(1) was called
 7256     (check-ints-equal *(edx+4) 2 "F - test-add-with-too-many-outputs: exit status")
 7257     # don't restore from ebp
 7258     81 0/subop/add %esp 8/imm32
 7259     # . epilogue
 7260     5d/pop-to-ebp
 7261     c3/return
 7262 
 7263 test-add-with-non-number:
 7264     # . prologue
 7265     55/push-ebp
 7266     89/<- %ebp 4/r32/esp
 7267     # setup
 7268     (clear-stream _test-input-stream)
 7269     (clear-stream $_test-input-buffered-file->buffer)
 7270     (clear-stream _test-output-stream)
 7271     (clear-stream $_test-output-buffered-file->buffer)
 7272     (clear-stream _test-error-stream)
 7273     (clear-stream $_test-error-buffered-file->buffer)
 7274     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7275     68/push 0/imm32
 7276     68/push 0/imm32
 7277     89/<- %edx 4/r32/esp
 7278     (tailor-exit-descriptor %edx 0x10)
 7279     #
 7280     (write _test-input-stream "fn foo {\n")
 7281     (write _test-input-stream "  var a: int\n")
 7282     (write _test-input-stream "  var b/ecx: (addr int) <- add a\n")
 7283     (write _test-input-stream "}\n")
 7284     # convert
 7285     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7286     # registers except esp clobbered at this point
 7287     # restore ed
 7288     89/<- %edx 4/r32/esp
 7289     (flush _test-output-buffered-file)
 7290     (flush _test-error-buffered-file)
 7291 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7297     # check output
 7298     (check-stream-equal _test-output-stream  ""  "F - test-add-with-non-number: output should be empty")
 7299     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt add: 'b' must be a non-addr non-offset scalar"  "F - test-add-with-non-number: error message")
 7300     # check that stop(1) was called
 7301     (check-ints-equal *(edx+4) 2 "F - test-add-with-non-number: exit status")
 7302     # don't restore from ebp
 7303     81 0/subop/add %esp 8/imm32
 7304     # . epilogue
 7305     5d/pop-to-ebp
 7306     c3/return
 7307 
 7308 test-add-with-addr-dereferenced:
 7309     # . prologue
 7310     55/push-ebp
 7311     89/<- %ebp 4/r32/esp
 7312     # setup
 7313     (clear-stream _test-input-stream)
 7314     (clear-stream $_test-input-buffered-file->buffer)
 7315     (clear-stream _test-output-stream)
 7316     (clear-stream $_test-output-buffered-file->buffer)
 7317     #
 7318     (write _test-input-stream "fn foo {\n")
 7319     (write _test-input-stream "  var a/eax: (addr int) <- copy 0\n")
 7320     (write _test-input-stream "  add-to *a, 1\n")
 7321     (write _test-input-stream "}\n")
 7322     # convert
 7323     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7324     (flush _test-output-buffered-file)
 7325     # no error
 7326     # . epilogue
 7327     89/<- %esp 5/r32/ebp
 7328     5d/pop-to-ebp
 7329     c3/return
 7330 
 7331 test-copy-with-no-inout:
 7332     # . prologue
 7333     55/push-ebp
 7334     89/<- %ebp 4/r32/esp
 7335     # setup
 7336     (clear-stream _test-input-stream)
 7337     (clear-stream $_test-input-buffered-file->buffer)
 7338     (clear-stream _test-output-stream)
 7339     (clear-stream $_test-output-buffered-file->buffer)
 7340     (clear-stream _test-error-stream)
 7341     (clear-stream $_test-error-buffered-file->buffer)
 7342     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7343     68/push 0/imm32
 7344     68/push 0/imm32
 7345     89/<- %edx 4/r32/esp
 7346     (tailor-exit-descriptor %edx 0x10)
 7347     #
 7348     (write _test-input-stream "fn foo {\n")
 7349     (write _test-input-stream "  var x/eax: boolean <- copy\n")
 7350     (write _test-input-stream "}\n")
 7351     # convert
 7352     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7353     # registers except esp clobbered at this point
 7354     # restore ed
 7355     89/<- %edx 4/r32/esp
 7356     (flush _test-output-buffered-file)
 7357     (flush _test-error-buffered-file)
 7358 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7364     # check output
 7365     (check-stream-equal _test-output-stream  ""  "F - test-copy-with-no-inout: output should be empty")
 7366     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy' expects an inout"  "F - test-copy-with-no-inout: error message")
 7367     # check that stop(1) was called
 7368     (check-ints-equal *(edx+4) 2 "F - test-copy-with-no-inout: exit status")
 7369     # don't restore from ebp
 7370     81 0/subop/add %esp 8/imm32
 7371     # . epilogue
 7372     5d/pop-to-ebp
 7373     c3/return
 7374 
 7375 test-copy-with-multiple-inouts:
 7376     # . prologue
 7377     55/push-ebp
 7378     89/<- %ebp 4/r32/esp
 7379     # setup
 7380     (clear-stream _test-input-stream)
 7381     (clear-stream $_test-input-buffered-file->buffer)
 7382     (clear-stream _test-output-stream)
 7383     (clear-stream $_test-output-buffered-file->buffer)
 7384     (clear-stream _test-error-stream)
 7385     (clear-stream $_test-error-buffered-file->buffer)
 7386     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7387     68/push 0/imm32
 7388     68/push 0/imm32
 7389     89/<- %edx 4/r32/esp
 7390     (tailor-exit-descriptor %edx 0x10)
 7391     #
 7392     (write _test-input-stream "fn foo {\n")
 7393     (write _test-input-stream "  var x/eax: boolean <- copy 0, 0\n")
 7394     (write _test-input-stream "}\n")
 7395     # convert
 7396     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7397     # registers except esp clobbered at this point
 7398     # restore ed
 7399     89/<- %edx 4/r32/esp
 7400     (flush _test-output-buffered-file)
 7401     (flush _test-error-buffered-file)
 7402 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7408     # check output
 7409     (check-stream-equal _test-output-stream  ""  "F - test-copy-with-multiple-inouts: output should be empty")
 7410     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy' must have just one inout"  "F - test-copy-with-multiple-inouts: error message")
 7411     # check that stop(1) was called
 7412     (check-ints-equal *(edx+4) 2 "F - test-copy-with-multiple-inouts: exit status")
 7413     # don't restore from ebp
 7414     81 0/subop/add %esp 8/imm32
 7415     # . epilogue
 7416     5d/pop-to-ebp
 7417     c3/return
 7418 
 7419 test-copy-with-no-output:
 7420     # . prologue
 7421     55/push-ebp
 7422     89/<- %ebp 4/r32/esp
 7423     # setup
 7424     (clear-stream _test-input-stream)
 7425     (clear-stream $_test-input-buffered-file->buffer)
 7426     (clear-stream _test-output-stream)
 7427     (clear-stream $_test-output-buffered-file->buffer)
 7428     (clear-stream _test-error-stream)
 7429     (clear-stream $_test-error-buffered-file->buffer)
 7430     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7431     68/push 0/imm32
 7432     68/push 0/imm32
 7433     89/<- %edx 4/r32/esp
 7434     (tailor-exit-descriptor %edx 0x10)
 7435     #
 7436     (write _test-input-stream "fn foo {\n")
 7437     (write _test-input-stream "  copy 0\n")
 7438     (write _test-input-stream "}\n")
 7439     # convert
 7440     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7441     # registers except esp clobbered at this point
 7442     # restore ed
 7443     89/<- %edx 4/r32/esp
 7444     (flush _test-output-buffered-file)
 7445     (flush _test-error-buffered-file)
 7446 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7452     # check output
 7453     (check-stream-equal _test-output-stream  ""  "F - test-copy-with-no-output: output should be empty")
 7454     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy' expects an output"  "F - test-copy-with-no-output: error message")
 7455     # check that stop(1) was called
 7456     (check-ints-equal *(edx+4) 2 "F - test-copy-with-no-output: exit status")
 7457     # don't restore from ebp
 7458     81 0/subop/add %esp 8/imm32
 7459     # . epilogue
 7460     5d/pop-to-ebp
 7461     c3/return
 7462 
 7463 test-copy-with-multiple-outputs:
 7464     # . prologue
 7465     55/push-ebp
 7466     89/<- %ebp 4/r32/esp
 7467     # setup
 7468     (clear-stream _test-input-stream)
 7469     (clear-stream $_test-input-buffered-file->buffer)
 7470     (clear-stream _test-output-stream)
 7471     (clear-stream $_test-output-buffered-file->buffer)
 7472     (clear-stream _test-error-stream)
 7473     (clear-stream $_test-error-buffered-file->buffer)
 7474     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7475     68/push 0/imm32
 7476     68/push 0/imm32
 7477     89/<- %edx 4/r32/esp
 7478     (tailor-exit-descriptor %edx 0x10)
 7479     #
 7480     (write _test-input-stream "fn foo {\n")
 7481     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
 7482     (write _test-input-stream "  var y/ecx: boolean <- copy 0\n")
 7483     (write _test-input-stream "  x, y <- copy 0\n")
 7484     (write _test-input-stream "}\n")
 7485     # convert
 7486     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7487     # registers except esp clobbered at this point
 7488     # restore ed
 7489     89/<- %edx 4/r32/esp
 7490     (flush _test-output-buffered-file)
 7491     (flush _test-error-buffered-file)
 7492 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7498     # check output
 7499     (check-stream-equal _test-output-stream  ""  "F - test-copy-with-multiple-outputs: output should be empty")
 7500     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy' must have just one output"  "F - test-copy-with-multiple-outputs: error message")
 7501     # check that stop(1) was called
 7502     (check-ints-equal *(edx+4) 2 "F - test-copy-with-multiple-outputs: exit status")
 7503     # don't restore from ebp
 7504     81 0/subop/add %esp 8/imm32
 7505     # . epilogue
 7506     5d/pop-to-ebp
 7507     c3/return
 7508 
 7509 test-copy-invalid-value-to-address:
 7510     # . prologue
 7511     55/push-ebp
 7512     89/<- %ebp 4/r32/esp
 7513     # setup
 7514     (clear-stream _test-input-stream)
 7515     (clear-stream $_test-input-buffered-file->buffer)
 7516     (clear-stream _test-output-stream)
 7517     (clear-stream $_test-output-buffered-file->buffer)
 7518     (clear-stream _test-error-stream)
 7519     (clear-stream $_test-error-buffered-file->buffer)
 7520     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7521     68/push 0/imm32
 7522     68/push 0/imm32
 7523     89/<- %edx 4/r32/esp
 7524     (tailor-exit-descriptor %edx 0x10)
 7525     #
 7526     (write _test-input-stream "fn foo {\n")
 7527     (write _test-input-stream "  var x/eax: int <- copy 0\n")
 7528     (write _test-input-stream "  var y/ecx: (addr int) <- copy x\n")
 7529     (write _test-input-stream "}\n")
 7530     # convert
 7531     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7532     # registers except esp clobbered at this point
 7533     # restore ed
 7534     89/<- %edx 4/r32/esp
 7535     (flush _test-output-buffered-file)
 7536     (flush _test-error-buffered-file)
 7537 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7543     # check output
 7544     (check-stream-equal _test-output-stream  ""  "F - test-copy-invalid-value-to-address: output should be empty")
 7545     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy: 'y' must be a non-addr non-offset scalar"  "F - test-copy-invalid-value-to-address: error message")
 7546     # check that stop(1) was called
 7547     (check-ints-equal *(edx+4) 2 "F - test-copy-invalid-value-to-address: exit status")
 7548     # don't restore from ebp
 7549     81 0/subop/add %esp 8/imm32
 7550     # . epilogue
 7551     5d/pop-to-ebp
 7552     c3/return
 7553 
 7554 test-copy-null-value-to-addr:
 7555     # . prologue
 7556     55/push-ebp
 7557     89/<- %ebp 4/r32/esp
 7558     # setup
 7559     (clear-stream _test-input-stream)
 7560     (clear-stream $_test-input-buffered-file->buffer)
 7561     (clear-stream _test-output-stream)
 7562     (clear-stream $_test-output-buffered-file->buffer)
 7563     #
 7564     (write _test-input-stream "fn foo {\n")
 7565     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
 7566     (write _test-input-stream "}\n")
 7567     # convert
 7568     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7569     (flush _test-output-buffered-file)
 7570 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7576     # no errors
 7577     # . epilogue
 7578     89/<- %esp 5/r32/ebp
 7579     5d/pop-to-ebp
 7580     c3/return
 7581 
 7582 test-copy-invalid-value-to-offset:
 7583     # . prologue
 7584     55/push-ebp
 7585     89/<- %ebp 4/r32/esp
 7586     # setup
 7587     (clear-stream _test-input-stream)
 7588     (clear-stream $_test-input-buffered-file->buffer)
 7589     (clear-stream _test-output-stream)
 7590     (clear-stream $_test-output-buffered-file->buffer)
 7591     (clear-stream _test-error-stream)
 7592     (clear-stream $_test-error-buffered-file->buffer)
 7593     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7594     68/push 0/imm32
 7595     68/push 0/imm32
 7596     89/<- %edx 4/r32/esp
 7597     (tailor-exit-descriptor %edx 0x10)
 7598     #
 7599     (write _test-input-stream "fn foo {\n")
 7600     (write _test-input-stream "  var x/eax: int <- copy 0\n")
 7601     (write _test-input-stream "  var y/ecx: (offset int) <- copy x\n")
 7602     (write _test-input-stream "}\n")
 7603     # convert
 7604     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7605     # registers except esp clobbered at this point
 7606     # restore ed
 7607     89/<- %edx 4/r32/esp
 7608     (flush _test-output-buffered-file)
 7609     (flush _test-error-buffered-file)
 7610 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7616     # check output
 7617     (check-stream-equal _test-output-stream  ""  "F - test-copy-invalid-value-to-address: output should be empty")
 7618     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy: 'y' must be a non-addr non-offset scalar"  "F - test-copy-invalid-value-to-address: error message")
 7619     # check that stop(1) was called
 7620     (check-ints-equal *(edx+4) 2 "F - test-copy-invalid-value-to-offset: exit status")
 7621     # don't restore from ebp
 7622     81 0/subop/add %esp 8/imm32
 7623     # . epilogue
 7624     5d/pop-to-ebp
 7625     c3/return
 7626 
 7627 test-copy-null-value-to-offset:
 7628     # . prologue
 7629     55/push-ebp
 7630     89/<- %ebp 4/r32/esp
 7631     # setup
 7632     (clear-stream _test-input-stream)
 7633     (clear-stream $_test-input-buffered-file->buffer)
 7634     (clear-stream _test-output-stream)
 7635     (clear-stream $_test-output-buffered-file->buffer)
 7636     #
 7637     (write _test-input-stream "fn foo {\n")
 7638     (write _test-input-stream "  var y/ecx: (offset int) <- copy 0\n")
 7639     (write _test-input-stream "}\n")
 7640     # convert
 7641     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7642     (flush _test-output-buffered-file)
 7643 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7649     # no errors
 7650     # . epilogue
 7651     89/<- %esp 5/r32/ebp
 7652     5d/pop-to-ebp
 7653     c3/return
 7654 
 7655 test-copy-deref-address:
 7656     # . prologue
 7657     55/push-ebp
 7658     89/<- %ebp 4/r32/esp
 7659     # setup
 7660     (clear-stream _test-input-stream)
 7661     (clear-stream $_test-input-buffered-file->buffer)
 7662     (clear-stream _test-output-stream)
 7663     (clear-stream $_test-output-buffered-file->buffer)
 7664     #
 7665     (write _test-input-stream "fn foo {\n")
 7666     (write _test-input-stream "  var x/eax: (addr addr int) <- copy 0\n")
 7667     (write _test-input-stream "  var y/ecx: (addr int) <- copy *x\n")
 7668     (write _test-input-stream "}\n")
 7669     # convert
 7670     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 7671     (flush _test-output-buffered-file)
 7672 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7678     # not bothering checking output
 7679     (check-next-stream-line-equal _test-error-stream  ""  "F - test-copy-deref-address: error message")
 7680     # . epilogue
 7681     5d/pop-to-ebp
 7682     c3/return
 7683 
 7684 test-copy-to-non-register:
 7685     # . prologue
 7686     55/push-ebp
 7687     89/<- %ebp 4/r32/esp
 7688     # setup
 7689     (clear-stream _test-input-stream)
 7690     (clear-stream $_test-input-buffered-file->buffer)
 7691     (clear-stream _test-output-stream)
 7692     (clear-stream $_test-output-buffered-file->buffer)
 7693     (clear-stream _test-error-stream)
 7694     (clear-stream $_test-error-buffered-file->buffer)
 7695     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7696     68/push 0/imm32
 7697     68/push 0/imm32
 7698     89/<- %edx 4/r32/esp
 7699     (tailor-exit-descriptor %edx 0x10)
 7700     #
 7701     (write _test-input-stream "fn foo {\n")
 7702     (write _test-input-stream "  var x: int\n")
 7703     (write _test-input-stream "  x <- copy 0\n")
 7704     (write _test-input-stream "}\n")
 7705     # convert
 7706     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7707     # registers except esp clobbered at this point
 7708     # restore ed
 7709     89/<- %edx 4/r32/esp
 7710     (flush _test-output-buffered-file)
 7711     (flush _test-error-buffered-file)
 7712 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7718     # check output
 7719     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-non-register: output should be empty")
 7720     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy: output 'x' not in a register"  "F - test-copy-to-non-register: error message")
 7721     # check that stop(1) was called
 7722     (check-ints-equal *(edx+4) 2 "F - test-copy-to-non-register: exit status")
 7723     # don't restore from ebp
 7724     81 0/subop/add %esp 8/imm32
 7725     # . epilogue
 7726     5d/pop-to-ebp
 7727     c3/return
 7728 
 7729 test-copy-non-scalar:
 7730     # . prologue
 7731     55/push-ebp
 7732     89/<- %ebp 4/r32/esp
 7733     # setup
 7734     (clear-stream _test-input-stream)
 7735     (clear-stream $_test-input-buffered-file->buffer)
 7736     (clear-stream _test-output-stream)
 7737     (clear-stream $_test-output-buffered-file->buffer)
 7738     (clear-stream _test-error-stream)
 7739     (clear-stream $_test-error-buffered-file->buffer)
 7740     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7741     68/push 0/imm32
 7742     68/push 0/imm32
 7743     89/<- %edx 4/r32/esp
 7744     (tailor-exit-descriptor %edx 0x10)
 7745     #
 7746     (write _test-input-stream "fn foo {\n")
 7747     (write _test-input-stream "  var x: (handle int)\n")
 7748     (write _test-input-stream "  var y/eax: int <- copy x\n")
 7749     (write _test-input-stream "}\n")
 7750     # convert
 7751     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7752     # registers except esp clobbered at this point
 7753     # restore ed
 7754     89/<- %edx 4/r32/esp
 7755     (flush _test-output-buffered-file)
 7756     (flush _test-error-buffered-file)
 7757 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7763     # check output
 7764     (check-stream-equal _test-output-stream  ""  "F - test-copy-non-scalar: output should be empty")
 7765     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy: 'x' is too large to fit in a register"  "F - test-copy-non-scalar: error message")
 7766     # check that stop(1) was called
 7767     (check-ints-equal *(edx+4) 2 "F - test-copy-non-scalar: exit status")
 7768     # don't restore from ebp
 7769     81 0/subop/add %esp 8/imm32
 7770     # . epilogue
 7771     5d/pop-to-ebp
 7772     c3/return
 7773 
 7774 test-copy-to-with-no-inout:
 7775     # . prologue
 7776     55/push-ebp
 7777     89/<- %ebp 4/r32/esp
 7778     # setup
 7779     (clear-stream _test-input-stream)
 7780     (clear-stream $_test-input-buffered-file->buffer)
 7781     (clear-stream _test-output-stream)
 7782     (clear-stream $_test-output-buffered-file->buffer)
 7783     (clear-stream _test-error-stream)
 7784     (clear-stream $_test-error-buffered-file->buffer)
 7785     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7786     68/push 0/imm32
 7787     68/push 0/imm32
 7788     89/<- %edx 4/r32/esp
 7789     (tailor-exit-descriptor %edx 0x10)
 7790     #
 7791     (write _test-input-stream "fn foo {\n")
 7792     (write _test-input-stream "  copy-to\n")
 7793     (write _test-input-stream "}\n")
 7794     # convert
 7795     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7796     # registers except esp clobbered at this point
 7797     # restore ed
 7798     89/<- %edx 4/r32/esp
 7799     (flush _test-output-buffered-file)
 7800     (flush _test-error-buffered-file)
 7801 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7807     # check output
 7808     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-with-no-inout: output should be empty")
 7809     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-to' must have two inouts"  "F - test-copy-to-with-no-inout: error message")
 7810     # check that stop(1) was called
 7811     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-no-inout: exit status")
 7812     # don't restore from ebp
 7813     81 0/subop/add %esp 8/imm32
 7814     # . epilogue
 7815     5d/pop-to-ebp
 7816     c3/return
 7817 
 7818 test-copy-to-with-no-input:
 7819     # . prologue
 7820     55/push-ebp
 7821     89/<- %ebp 4/r32/esp
 7822     # setup
 7823     (clear-stream _test-input-stream)
 7824     (clear-stream $_test-input-buffered-file->buffer)
 7825     (clear-stream _test-output-stream)
 7826     (clear-stream $_test-output-buffered-file->buffer)
 7827     (clear-stream _test-error-stream)
 7828     (clear-stream $_test-error-buffered-file->buffer)
 7829     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7830     68/push 0/imm32
 7831     68/push 0/imm32
 7832     89/<- %edx 4/r32/esp
 7833     (tailor-exit-descriptor %edx 0x10)
 7834     #
 7835     (write _test-input-stream "fn foo {\n")
 7836     (write _test-input-stream "  var x: boolean\n")
 7837     (write _test-input-stream "  copy-to x\n")
 7838     (write _test-input-stream "}\n")
 7839     # convert
 7840     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7841     # registers except esp clobbered at this point
 7842     # restore ed
 7843     89/<- %edx 4/r32/esp
 7844     (flush _test-output-buffered-file)
 7845     (flush _test-error-buffered-file)
 7846 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7852     # check output
 7853     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-with-no-input: output should be empty")
 7854     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-to' must have two inouts"  "F - test-copy-to-with-no-input: error message")
 7855     # check that stop(1) was called
 7856     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-no-input: exit status")
 7857     # don't restore from ebp
 7858     81 0/subop/add %esp 8/imm32
 7859     # . epilogue
 7860     5d/pop-to-ebp
 7861     c3/return
 7862 
 7863 test-copy-to-with-no-register:
 7864     # . prologue
 7865     55/push-ebp
 7866     89/<- %ebp 4/r32/esp
 7867     # setup
 7868     (clear-stream _test-input-stream)
 7869     (clear-stream $_test-input-buffered-file->buffer)
 7870     (clear-stream _test-output-stream)
 7871     (clear-stream $_test-output-buffered-file->buffer)
 7872     (clear-stream _test-error-stream)
 7873     (clear-stream $_test-error-buffered-file->buffer)
 7874     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7875     68/push 0/imm32
 7876     68/push 0/imm32
 7877     89/<- %edx 4/r32/esp
 7878     (tailor-exit-descriptor %edx 0x10)
 7879     #
 7880     (write _test-input-stream "fn foo {\n")
 7881     (write _test-input-stream "  var x: boolean\n")
 7882     (write _test-input-stream "  copy-to x, x\n")
 7883     (write _test-input-stream "}\n")
 7884     # convert
 7885     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7886     # registers except esp clobbered at this point
 7887     # restore ed
 7888     89/<- %edx 4/r32/esp
 7889     (flush _test-output-buffered-file)
 7890     (flush _test-error-buffered-file)
 7891 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7897     # check output
 7898     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-with-no-register: output should be empty")
 7899     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-to: source (second inout) is in memory"  "F - test-copy-to-with-no-register: error message")
 7900     # check that stop(1) was called
 7901     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-no-register: exit status")
 7902     # don't restore from ebp
 7903     81 0/subop/add %esp 8/imm32
 7904     # . epilogue
 7905     5d/pop-to-ebp
 7906     c3/return
 7907 
 7908 test-copy-to-with-too-many-inouts:
 7909     # . prologue
 7910     55/push-ebp
 7911     89/<- %ebp 4/r32/esp
 7912     # setup
 7913     (clear-stream _test-input-stream)
 7914     (clear-stream $_test-input-buffered-file->buffer)
 7915     (clear-stream _test-output-stream)
 7916     (clear-stream $_test-output-buffered-file->buffer)
 7917     (clear-stream _test-error-stream)
 7918     (clear-stream $_test-error-buffered-file->buffer)
 7919     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7920     68/push 0/imm32
 7921     68/push 0/imm32
 7922     89/<- %edx 4/r32/esp
 7923     (tailor-exit-descriptor %edx 0x10)
 7924     #
 7925     (write _test-input-stream "fn foo {\n")
 7926     (write _test-input-stream "  var x: boolean\n")
 7927     (write _test-input-stream "  copy-to x, 0, 0\n")
 7928     (write _test-input-stream "}\n")
 7929     # convert
 7930     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7931     # registers except esp clobbered at this point
 7932     # restore ed
 7933     89/<- %edx 4/r32/esp
 7934     (flush _test-output-buffered-file)
 7935     (flush _test-error-buffered-file)
 7936 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7942     # check output
 7943     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-with-too-many-inouts: output should be empty")
 7944     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-to' must have two inouts"  "F - test-copy-to-with-too-many-inouts: error message")
 7945     # check that stop(1) was called
 7946     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-too-many-inouts: exit status")
 7947     # don't restore from ebp
 7948     81 0/subop/add %esp 8/imm32
 7949     # . epilogue
 7950     5d/pop-to-ebp
 7951     c3/return
 7952 
 7953 test-copy-to-with-output:
 7954     # . prologue
 7955     55/push-ebp
 7956     89/<- %ebp 4/r32/esp
 7957     # setup
 7958     (clear-stream _test-input-stream)
 7959     (clear-stream $_test-input-buffered-file->buffer)
 7960     (clear-stream _test-output-stream)
 7961     (clear-stream $_test-output-buffered-file->buffer)
 7962     (clear-stream _test-error-stream)
 7963     (clear-stream $_test-error-buffered-file->buffer)
 7964     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 7965     68/push 0/imm32
 7966     68/push 0/imm32
 7967     89/<- %edx 4/r32/esp
 7968     (tailor-exit-descriptor %edx 0x10)
 7969     #
 7970     (write _test-input-stream "fn foo {\n")
 7971     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
 7972     (write _test-input-stream "  var y/ecx: boolean <- copy 0\n")
 7973     (write _test-input-stream "  x <- copy-to y, 0\n")
 7974     (write _test-input-stream "}\n")
 7975     # convert
 7976     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 7977     # registers except esp clobbered at this point
 7978     # restore ed
 7979     89/<- %edx 4/r32/esp
 7980     (flush _test-output-buffered-file)
 7981     (flush _test-error-buffered-file)
 7982 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 7988     # check output
 7989     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-with-output: output should be empty")
 7990     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-to' must not have any outputs"  "F - test-copy-to-with-output: error message")
 7991     # check that stop(1) was called
 7992     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-output: exit status")
 7993     # don't restore from ebp
 7994     81 0/subop/add %esp 8/imm32
 7995     # . epilogue
 7996     5d/pop-to-ebp
 7997     c3/return
 7998 
 7999 test-copy-to-invalid-value-to-address:
 8000     # . prologue
 8001     55/push-ebp
 8002     89/<- %ebp 4/r32/esp
 8003     # setup
 8004     (clear-stream _test-input-stream)
 8005     (clear-stream $_test-input-buffered-file->buffer)
 8006     (clear-stream _test-output-stream)
 8007     (clear-stream $_test-output-buffered-file->buffer)
 8008     (clear-stream _test-error-stream)
 8009     (clear-stream $_test-error-buffered-file->buffer)
 8010     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8011     68/push 0/imm32
 8012     68/push 0/imm32
 8013     89/<- %edx 4/r32/esp
 8014     (tailor-exit-descriptor %edx 0x10)
 8015     #
 8016     (write _test-input-stream "fn foo {\n")
 8017     (write _test-input-stream "  var x/eax: int <- copy 0\n")
 8018     (write _test-input-stream "  var y: (addr int)\n")
 8019     (write _test-input-stream "  copy-to y, x\n")
 8020     (write _test-input-stream "}\n")
 8021     # convert
 8022     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8023     # registers except esp clobbered at this point
 8024     # restore ed
 8025     89/<- %edx 4/r32/esp
 8026     (flush _test-output-buffered-file)
 8027     (flush _test-error-buffered-file)
 8028 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8034     # check output
 8035     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-invalid-value-to-address: output should be empty")
 8036     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-to: 'y' must be a non-addr non-offset scalar"  "F - test-copy-to-invalid-value-to-address: error message")
 8037     # check that stop(1) was called
 8038     (check-ints-equal *(edx+4) 2 "F - test-copy-to-invalid-value-to-address: exit status")
 8039     # don't restore from ebp
 8040     81 0/subop/add %esp 8/imm32
 8041     # . epilogue
 8042     5d/pop-to-ebp
 8043     c3/return
 8044 
 8045 test-copy-to-deref-address:
 8046     # . prologue
 8047     55/push-ebp
 8048     89/<- %ebp 4/r32/esp
 8049     # setup
 8050     (clear-stream _test-input-stream)
 8051     (clear-stream $_test-input-buffered-file->buffer)
 8052     (clear-stream _test-output-stream)
 8053     (clear-stream $_test-output-buffered-file->buffer)
 8054     #
 8055     (write _test-input-stream "fn foo {\n")
 8056     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
 8057     (write _test-input-stream "  var y/ecx: (addr addr int) <- copy 0\n")
 8058     (write _test-input-stream "  copy-to *y, x\n")
 8059     (write _test-input-stream "}\n")
 8060     # convert
 8061     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 8062     (flush _test-output-buffered-file)
 8063 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8069     # not bothering checking output
 8070     (check-next-stream-line-equal _test-error-stream  ""  "F - test-copy-to-deref-address: error message")
 8071     # . epilogue
 8072     5d/pop-to-ebp
 8073     c3/return
 8074 
 8075 test-copy-to-non-scalar:
 8076     # . prologue
 8077     55/push-ebp
 8078     89/<- %ebp 4/r32/esp
 8079     # setup
 8080     (clear-stream _test-input-stream)
 8081     (clear-stream $_test-input-buffered-file->buffer)
 8082     (clear-stream _test-output-stream)
 8083     (clear-stream $_test-output-buffered-file->buffer)
 8084     (clear-stream _test-error-stream)
 8085     (clear-stream $_test-error-buffered-file->buffer)
 8086     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8087     68/push 0/imm32
 8088     68/push 0/imm32
 8089     89/<- %edx 4/r32/esp
 8090     (tailor-exit-descriptor %edx 0x10)
 8091     #
 8092     (write _test-input-stream "fn foo {\n")
 8093     (write _test-input-stream "  var x: (handle int)\n")
 8094     (write _test-input-stream "  var y: int\n")
 8095     (write _test-input-stream "  copy-to y, x\n")
 8096     (write _test-input-stream "}\n")
 8097     # convert
 8098     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8099     # registers except esp clobbered at this point
 8100     # restore ed
 8101     89/<- %edx 4/r32/esp
 8102     (flush _test-output-buffered-file)
 8103     (flush _test-error-buffered-file)
 8104 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8110     # check output
 8111     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-non-scalar: output should be empty")
 8112 #?     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-to: 'x' is too large to copy"  "F - test-copy-to-non-scalar: error message")
 8113     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-to: source (second inout) is in memory"  "F - test-copy-to-non-scalar: error message")
 8114     # check that stop(1) was called
 8115     (check-ints-equal *(edx+4) 2 "F - test-copy-to-non-scalar: exit status")
 8116     # don't restore from ebp
 8117     81 0/subop/add %esp 8/imm32
 8118     # . epilogue
 8119     5d/pop-to-ebp
 8120     c3/return
 8121 
 8122 test-compare-with-no-inout:
 8123     # . prologue
 8124     55/push-ebp
 8125     89/<- %ebp 4/r32/esp
 8126     # setup
 8127     (clear-stream _test-input-stream)
 8128     (clear-stream $_test-input-buffered-file->buffer)
 8129     (clear-stream _test-output-stream)
 8130     (clear-stream $_test-output-buffered-file->buffer)
 8131     (clear-stream _test-error-stream)
 8132     (clear-stream $_test-error-buffered-file->buffer)
 8133     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8134     68/push 0/imm32
 8135     68/push 0/imm32
 8136     89/<- %edx 4/r32/esp
 8137     (tailor-exit-descriptor %edx 0x10)
 8138     #
 8139     (write _test-input-stream "fn foo {\n")
 8140     (write _test-input-stream "  var x: boolean\n")
 8141     (write _test-input-stream "  compare\n")
 8142     (write _test-input-stream "}\n")
 8143     # convert
 8144     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8145     # registers except esp clobbered at this point
 8146     # restore ed
 8147     89/<- %edx 4/r32/esp
 8148     (flush _test-output-buffered-file)
 8149     (flush _test-error-buffered-file)
 8150 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8156     # check output
 8157     (check-stream-equal _test-output-stream  ""  "F - test-compare-with-no-inout: output should be empty")
 8158     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'compare' must have two inouts"  "F - test-compare-with-no-inout: error message")
 8159     # check that stop(1) was called
 8160     (check-ints-equal *(edx+4) 2 "F - test-compare-with-no-inout: exit status")
 8161     # don't restore from ebp
 8162     81 0/subop/add %esp 8/imm32
 8163     # . epilogue
 8164     5d/pop-to-ebp
 8165     c3/return
 8166 
 8167 test-compare-with-no-input:
 8168     # . prologue
 8169     55/push-ebp
 8170     89/<- %ebp 4/r32/esp
 8171     # setup
 8172     (clear-stream _test-input-stream)
 8173     (clear-stream $_test-input-buffered-file->buffer)
 8174     (clear-stream _test-output-stream)
 8175     (clear-stream $_test-output-buffered-file->buffer)
 8176     (clear-stream _test-error-stream)
 8177     (clear-stream $_test-error-buffered-file->buffer)
 8178     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8179     68/push 0/imm32
 8180     68/push 0/imm32
 8181     89/<- %edx 4/r32/esp
 8182     (tailor-exit-descriptor %edx 0x10)
 8183     #
 8184     (write _test-input-stream "fn foo {\n")
 8185     (write _test-input-stream "  var x: boolean\n")
 8186     (write _test-input-stream "  compare x\n")
 8187     (write _test-input-stream "}\n")
 8188     # convert
 8189     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8190     # registers except esp clobbered at this point
 8191     # restore ed
 8192     89/<- %edx 4/r32/esp
 8193     (flush _test-output-buffered-file)
 8194     (flush _test-error-buffered-file)
 8195 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8201     # check output
 8202     (check-stream-equal _test-output-stream  ""  "F - test-compare-with-no-input: output should be empty")
 8203     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'compare' must have two inouts"  "F - test-compare-with-no-input: error message")
 8204     # check that stop(1) was called
 8205     (check-ints-equal *(edx+4) 2 "F - test-compare-with-no-input: exit status")
 8206     # don't restore from ebp
 8207     81 0/subop/add %esp 8/imm32
 8208     # . epilogue
 8209     5d/pop-to-ebp
 8210     c3/return
 8211 
 8212 test-compare-with-too-many-inouts:
 8213     # . prologue
 8214     55/push-ebp
 8215     89/<- %ebp 4/r32/esp
 8216     # setup
 8217     (clear-stream _test-input-stream)
 8218     (clear-stream $_test-input-buffered-file->buffer)
 8219     (clear-stream _test-output-stream)
 8220     (clear-stream $_test-output-buffered-file->buffer)
 8221     (clear-stream _test-error-stream)
 8222     (clear-stream $_test-error-buffered-file->buffer)
 8223     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8224     68/push 0/imm32
 8225     68/push 0/imm32
 8226     89/<- %edx 4/r32/esp
 8227     (tailor-exit-descriptor %edx 0x10)
 8228     #
 8229     (write _test-input-stream "fn foo {\n")
 8230     (write _test-input-stream "  var x: boolean\n")
 8231     (write _test-input-stream "  compare x, 0, 0\n")
 8232     (write _test-input-stream "}\n")
 8233     # convert
 8234     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8235     # registers except esp clobbered at this point
 8236     # restore ed
 8237     89/<- %edx 4/r32/esp
 8238     (flush _test-output-buffered-file)
 8239     (flush _test-error-buffered-file)
 8240 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8246     # check output
 8247     (check-stream-equal _test-output-stream  ""  "F - test-compare-with-too-many-inouts: output should be empty")
 8248     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'compare' must have two inouts"  "F - test-compare-with-too-many-inouts: error message")
 8249     # check that stop(1) was called
 8250     (check-ints-equal *(edx+4) 2 "F - test-compare-with-too-many-inouts: exit status")
 8251     # don't restore from ebp
 8252     81 0/subop/add %esp 8/imm32
 8253     # . epilogue
 8254     5d/pop-to-ebp
 8255     c3/return
 8256 
 8257 test-compare-with-output:
 8258     # . prologue
 8259     55/push-ebp
 8260     89/<- %ebp 4/r32/esp
 8261     # setup
 8262     (clear-stream _test-input-stream)
 8263     (clear-stream $_test-input-buffered-file->buffer)
 8264     (clear-stream _test-output-stream)
 8265     (clear-stream $_test-output-buffered-file->buffer)
 8266     (clear-stream _test-error-stream)
 8267     (clear-stream $_test-error-buffered-file->buffer)
 8268     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8269     68/push 0/imm32
 8270     68/push 0/imm32
 8271     89/<- %edx 4/r32/esp
 8272     (tailor-exit-descriptor %edx 0x10)
 8273     #
 8274     (write _test-input-stream "fn foo {\n")
 8275     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
 8276     (write _test-input-stream "  var y/ecx: boolean <- copy 0\n")
 8277     (write _test-input-stream "  x <- compare y, 0\n")
 8278     (write _test-input-stream "}\n")
 8279     # convert
 8280     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8281     # registers except esp clobbered at this point
 8282     # restore ed
 8283     89/<- %edx 4/r32/esp
 8284     (flush _test-output-buffered-file)
 8285     (flush _test-error-buffered-file)
 8286 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8292     # check output
 8293     (check-stream-equal _test-output-stream  ""  "F - test-compare-with-output: output should be empty")
 8294     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'compare' must not have any outputs"  "F - test-compare-with-output: error message")
 8295     # check that stop(1) was called
 8296     (check-ints-equal *(edx+4) 2 "F - test-compare-with-output: exit status")
 8297     # don't restore from ebp
 8298     81 0/subop/add %esp 8/imm32
 8299     # . epilogue
 8300     5d/pop-to-ebp
 8301     c3/return
 8302 
 8303 test-compare-invalid-value-to-address:
 8304     # . prologue
 8305     55/push-ebp
 8306     89/<- %ebp 4/r32/esp
 8307     # setup
 8308     (clear-stream _test-input-stream)
 8309     (clear-stream $_test-input-buffered-file->buffer)
 8310     (clear-stream _test-output-stream)
 8311     (clear-stream $_test-output-buffered-file->buffer)
 8312     (clear-stream _test-error-stream)
 8313     (clear-stream $_test-error-buffered-file->buffer)
 8314     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8315     68/push 0/imm32
 8316     68/push 0/imm32
 8317     89/<- %edx 4/r32/esp
 8318     (tailor-exit-descriptor %edx 0x10)
 8319     #
 8320     (write _test-input-stream "fn foo {\n")
 8321     (write _test-input-stream "  var x/eax: int <- copy 0\n")
 8322     (write _test-input-stream "  var y: (addr int)\n")
 8323     (write _test-input-stream "  compare y, x\n")
 8324     (write _test-input-stream "}\n")
 8325     # convert
 8326     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8327     # registers except esp clobbered at this point
 8328     # restore ed
 8329     89/<- %edx 4/r32/esp
 8330     (flush _test-output-buffered-file)
 8331     (flush _test-error-buffered-file)
 8332 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8338     # check output
 8339     (check-stream-equal _test-output-stream  ""  "F - test-compare-invalid-value-to-address: output should be empty")
 8340     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compare: 'y' must be a non-addr non-offset scalar"  "F - test-compare-invalid-value-to-address: error message")
 8341     # check that stop(1) was called
 8342     (check-ints-equal *(edx+4) 2 "F - test-compare-invalid-value-to-address: exit status")
 8343     # don't restore from ebp
 8344     81 0/subop/add %esp 8/imm32
 8345     # . epilogue
 8346     5d/pop-to-ebp
 8347     c3/return
 8348 
 8349 test-compare-address:
 8350     # . prologue
 8351     55/push-ebp
 8352     89/<- %ebp 4/r32/esp
 8353     # setup
 8354     (clear-stream _test-input-stream)
 8355     (clear-stream $_test-input-buffered-file->buffer)
 8356     (clear-stream _test-output-stream)
 8357     (clear-stream $_test-output-buffered-file->buffer)
 8358     #
 8359     (write _test-input-stream "fn foo {\n")
 8360     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
 8361     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
 8362     (write _test-input-stream "  compare y, x\n")
 8363     (write _test-input-stream "}\n")
 8364     # convert
 8365     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 8366     (flush _test-output-buffered-file)
 8367 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8373     # not bothering checking output
 8374     (check-next-stream-line-equal _test-error-stream  ""  "F - test-compare-address: error message")
 8375     # . epilogue
 8376     5d/pop-to-ebp
 8377     c3/return
 8378 
 8379 test-compare-deref-address:
 8380     # . prologue
 8381     55/push-ebp
 8382     89/<- %ebp 4/r32/esp
 8383     # setup
 8384     (clear-stream _test-input-stream)
 8385     (clear-stream $_test-input-buffered-file->buffer)
 8386     (clear-stream _test-output-stream)
 8387     (clear-stream $_test-output-buffered-file->buffer)
 8388     #
 8389     (write _test-input-stream "fn foo {\n")
 8390     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
 8391     (write _test-input-stream "  var y/ecx: (addr addr int) <- copy 0\n")
 8392     (write _test-input-stream "  compare *y, x\n")
 8393     (write _test-input-stream "}\n")
 8394     # convert
 8395     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 8396     (flush _test-output-buffered-file)
 8397 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8403     # not bothering checking output
 8404     (check-next-stream-line-equal _test-error-stream  ""  "F - test-compare-deref-address: error message")
 8405     # . epilogue
 8406     5d/pop-to-ebp
 8407     c3/return
 8408 
 8409 test-compare-two-vars-in-memory:
 8410     # . prologue
 8411     55/push-ebp
 8412     89/<- %ebp 4/r32/esp
 8413     # setup
 8414     (clear-stream _test-input-stream)
 8415     (clear-stream $_test-input-buffered-file->buffer)
 8416     (clear-stream _test-output-stream)
 8417     (clear-stream $_test-output-buffered-file->buffer)
 8418     (clear-stream _test-error-stream)
 8419     (clear-stream $_test-error-buffered-file->buffer)
 8420     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8421     68/push 0/imm32
 8422     68/push 0/imm32
 8423     89/<- %edx 4/r32/esp
 8424     (tailor-exit-descriptor %edx 0x10)
 8425     #
 8426     (write _test-input-stream "fn foo {\n")
 8427     (write _test-input-stream "  var x: boolean\n")
 8428     (write _test-input-stream "  compare x, x\n")
 8429     (write _test-input-stream "}\n")
 8430     # convert
 8431     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8432     # registers except esp clobbered at this point
 8433     # restore ed
 8434     89/<- %edx 4/r32/esp
 8435     (flush _test-output-buffered-file)
 8436     (flush _test-error-buffered-file)
 8437 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8443     # check output
 8444     (check-stream-equal _test-output-stream  ""  "F - test-compare-two-vars-in-memory: output should be empty")
 8445     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compare: both inouts are in memory"  "F - test-compare-two-vars-in-memory: error message")
 8446     # check that stop(1) was called
 8447     (check-ints-equal *(edx+4) 2 "F - test-compare-two-vars-in-memory: exit status")
 8448     # don't restore from ebp
 8449     81 0/subop/add %esp 8/imm32
 8450     # . epilogue
 8451     5d/pop-to-ebp
 8452     c3/return
 8453 
 8454 test-compare-non-scalar:
 8455     # . prologue
 8456     55/push-ebp
 8457     89/<- %ebp 4/r32/esp
 8458     # setup
 8459     (clear-stream _test-input-stream)
 8460     (clear-stream $_test-input-buffered-file->buffer)
 8461     (clear-stream _test-output-stream)
 8462     (clear-stream $_test-output-buffered-file->buffer)
 8463     (clear-stream _test-error-stream)
 8464     (clear-stream $_test-error-buffered-file->buffer)
 8465     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8466     68/push 0/imm32
 8467     68/push 0/imm32
 8468     89/<- %edx 4/r32/esp
 8469     (tailor-exit-descriptor %edx 0x10)
 8470     #
 8471     (write _test-input-stream "fn foo {\n")
 8472     (write _test-input-stream "  var x: (handle int)\n")
 8473     (write _test-input-stream "  var y: int\n")
 8474     (write _test-input-stream "  compare y, x\n")
 8475     (write _test-input-stream "}\n")
 8476     # convert
 8477     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8478     # registers except esp clobbered at this point
 8479     # restore ed
 8480     89/<- %edx 4/r32/esp
 8481     (flush _test-output-buffered-file)
 8482     (flush _test-error-buffered-file)
 8483 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8489     # check output
 8490     (check-stream-equal _test-output-stream  ""  "F - test-compare-non-scalar: output should be empty")
 8491 #?     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compare: 'x' is too large to compare"  "F - test-compare-non-scalar: error message")
 8492     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compare: both inouts are in memory"  "F - test-compare-non-scalar: error message")
 8493     # check that stop(1) was called
 8494     (check-ints-equal *(edx+4) 2 "F - test-compare-non-scalar: exit status")
 8495     # don't restore from ebp
 8496     81 0/subop/add %esp 8/imm32
 8497     # . epilogue
 8498     5d/pop-to-ebp
 8499     c3/return
 8500 
 8501 test-address-with-no-inout:
 8502     # . prologue
 8503     55/push-ebp
 8504     89/<- %ebp 4/r32/esp
 8505     # setup
 8506     (clear-stream _test-input-stream)
 8507     (clear-stream $_test-input-buffered-file->buffer)
 8508     (clear-stream _test-output-stream)
 8509     (clear-stream $_test-output-buffered-file->buffer)
 8510     (clear-stream _test-error-stream)
 8511     (clear-stream $_test-error-buffered-file->buffer)
 8512     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8513     68/push 0/imm32
 8514     68/push 0/imm32
 8515     89/<- %edx 4/r32/esp
 8516     (tailor-exit-descriptor %edx 0x10)
 8517     #
 8518     (write _test-input-stream "fn foo {\n")
 8519     (write _test-input-stream "  var x/eax: boolean <- address\n")
 8520     (write _test-input-stream "}\n")
 8521     # convert
 8522     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8523     # registers except esp clobbered at this point
 8524     # restore ed
 8525     89/<- %edx 4/r32/esp
 8526     (flush _test-output-buffered-file)
 8527     (flush _test-error-buffered-file)
 8528 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8534     # check output
 8535     (check-stream-equal _test-output-stream  ""  "F - test-address-with-no-inout: output should be empty")
 8536     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'address' expects an inout"  "F - test-address-with-no-inout: error message")
 8537     # check that stop(1) was called
 8538     (check-ints-equal *(edx+4) 2 "F - test-address-with-no-inout: exit status")
 8539     # don't restore from ebp
 8540     81 0/subop/add %esp 8/imm32
 8541     # . epilogue
 8542     5d/pop-to-ebp
 8543     c3/return
 8544 
 8545 test-address-with-multiple-inouts:
 8546     # . prologue
 8547     55/push-ebp
 8548     89/<- %ebp 4/r32/esp
 8549     # setup
 8550     (clear-stream _test-input-stream)
 8551     (clear-stream $_test-input-buffered-file->buffer)
 8552     (clear-stream _test-output-stream)
 8553     (clear-stream $_test-output-buffered-file->buffer)
 8554     (clear-stream _test-error-stream)
 8555     (clear-stream $_test-error-buffered-file->buffer)
 8556     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8557     68/push 0/imm32
 8558     68/push 0/imm32
 8559     89/<- %edx 4/r32/esp
 8560     (tailor-exit-descriptor %edx 0x10)
 8561     #
 8562     (write _test-input-stream "fn foo {\n")
 8563     (write _test-input-stream "  var x/eax: boolean <- address 0, 0\n")
 8564     (write _test-input-stream "}\n")
 8565     # convert
 8566     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8567     # registers except esp clobbered at this point
 8568     # restore ed
 8569     89/<- %edx 4/r32/esp
 8570     (flush _test-output-buffered-file)
 8571     (flush _test-error-buffered-file)
 8572 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8578     # check output
 8579     (check-stream-equal _test-output-stream  ""  "F - test-address-with-multiple-inouts: output should be empty")
 8580     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'address' must have just one inout"  "F - test-address-with-multiple-inouts: error message")
 8581     # check that stop(1) was called
 8582     (check-ints-equal *(edx+4) 2 "F - test-address-with-multiple-inouts: exit status")
 8583     # don't restore from ebp
 8584     81 0/subop/add %esp 8/imm32
 8585     # . epilogue
 8586     5d/pop-to-ebp
 8587     c3/return
 8588 
 8589 test-address-with-no-output:
 8590     # . prologue
 8591     55/push-ebp
 8592     89/<- %ebp 4/r32/esp
 8593     # setup
 8594     (clear-stream _test-input-stream)
 8595     (clear-stream $_test-input-buffered-file->buffer)
 8596     (clear-stream _test-output-stream)
 8597     (clear-stream $_test-output-buffered-file->buffer)
 8598     (clear-stream _test-error-stream)
 8599     (clear-stream $_test-error-buffered-file->buffer)
 8600     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8601     68/push 0/imm32
 8602     68/push 0/imm32
 8603     89/<- %edx 4/r32/esp
 8604     (tailor-exit-descriptor %edx 0x10)
 8605     #
 8606     (write _test-input-stream "fn foo {\n")
 8607     (write _test-input-stream "  address 0\n")
 8608     (write _test-input-stream "}\n")
 8609     # convert
 8610     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8611     # registers except esp clobbered at this point
 8612     # restore ed
 8613     89/<- %edx 4/r32/esp
 8614     (flush _test-output-buffered-file)
 8615     (flush _test-error-buffered-file)
 8616 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8622     # check output
 8623     (check-stream-equal _test-output-stream  ""  "F - test-address-with-no-output: output should be empty")
 8624     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'address' expects an output"  "F - test-address-with-no-output: error message")
 8625     # check that stop(1) was called
 8626     (check-ints-equal *(edx+4) 2 "F - test-address-with-no-output: exit status")
 8627     # don't restore from ebp
 8628     81 0/subop/add %esp 8/imm32
 8629     # . epilogue
 8630     5d/pop-to-ebp
 8631     c3/return
 8632 
 8633 test-address-with-multiple-outputs:
 8634     # . prologue
 8635     55/push-ebp
 8636     89/<- %ebp 4/r32/esp
 8637     # setup
 8638     (clear-stream _test-input-stream)
 8639     (clear-stream $_test-input-buffered-file->buffer)
 8640     (clear-stream _test-output-stream)
 8641     (clear-stream $_test-output-buffered-file->buffer)
 8642     (clear-stream _test-error-stream)
 8643     (clear-stream $_test-error-buffered-file->buffer)
 8644     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8645     68/push 0/imm32
 8646     68/push 0/imm32
 8647     89/<- %edx 4/r32/esp
 8648     (tailor-exit-descriptor %edx 0x10)
 8649     #
 8650     (write _test-input-stream "fn foo {\n")
 8651     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
 8652     (write _test-input-stream "  var y/ecx: boolean <- copy 0\n")
 8653     (write _test-input-stream "  x, y <- address 0\n")
 8654     (write _test-input-stream "}\n")
 8655     # convert
 8656     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8657     # registers except esp clobbered at this point
 8658     # restore ed
 8659     89/<- %edx 4/r32/esp
 8660     (flush _test-output-buffered-file)
 8661     (flush _test-error-buffered-file)
 8662 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8668     # check output
 8669     (check-stream-equal _test-output-stream  ""  "F - test-address-with-multiple-outputs: output should be empty")
 8670     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'address' must have just one output"  "F - test-address-with-multiple-outputs: error message")
 8671     # check that stop(1) was called
 8672     (check-ints-equal *(edx+4) 2 "F - test-address-with-multiple-outputs: exit status")
 8673     # don't restore from ebp
 8674     81 0/subop/add %esp 8/imm32
 8675     # . epilogue
 8676     5d/pop-to-ebp
 8677     c3/return
 8678 
 8679 # silly but it works
 8680 test-address-of-deref:
 8681     # . prologue
 8682     55/push-ebp
 8683     89/<- %ebp 4/r32/esp
 8684     # setup
 8685     (clear-stream _test-input-stream)
 8686     (clear-stream $_test-input-buffered-file->buffer)
 8687     (clear-stream _test-output-stream)
 8688     (clear-stream $_test-output-buffered-file->buffer)
 8689     #
 8690     (write _test-input-stream "fn foo {\n")
 8691     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
 8692     (write _test-input-stream "  var y/ecx: (addr int) <- address *x\n")
 8693     (write _test-input-stream "}\n")
 8694     # convert
 8695     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 8696     (flush _test-output-buffered-file)
 8697 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8703     # not bothering checking output
 8704     (check-next-stream-line-equal _test-error-stream  ""  "F - test-address-of-deref: error message")
 8705     # . epilogue
 8706     5d/pop-to-ebp
 8707     c3/return
 8708 
 8709 test-address-to-non-register:
 8710     # . prologue
 8711     55/push-ebp
 8712     89/<- %ebp 4/r32/esp
 8713     # setup
 8714     (clear-stream _test-input-stream)
 8715     (clear-stream $_test-input-buffered-file->buffer)
 8716     (clear-stream _test-output-stream)
 8717     (clear-stream $_test-output-buffered-file->buffer)
 8718     (clear-stream _test-error-stream)
 8719     (clear-stream $_test-error-buffered-file->buffer)
 8720     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8721     68/push 0/imm32
 8722     68/push 0/imm32
 8723     89/<- %edx 4/r32/esp
 8724     (tailor-exit-descriptor %edx 0x10)
 8725     #
 8726     (write _test-input-stream "fn foo {\n")
 8727     (write _test-input-stream "  var x: (addr int)\n")
 8728     (write _test-input-stream "  x <- address 0\n")
 8729     (write _test-input-stream "}\n")
 8730     # convert
 8731     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8732     # registers except esp clobbered at this point
 8733     # restore ed
 8734     89/<- %edx 4/r32/esp
 8735     (flush _test-output-buffered-file)
 8736     (flush _test-error-buffered-file)
 8737 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8743     # check output
 8744     (check-stream-equal _test-output-stream  ""  "F - test-address-to-non-register: output should be empty")
 8745     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt address: output 'x' not in a register"  "F - test-address-to-non-register: error message")
 8746     # check that stop(1) was called
 8747     (check-ints-equal *(edx+4) 2 "F - test-address-to-non-register: exit status")
 8748     # don't restore from ebp
 8749     81 0/subop/add %esp 8/imm32
 8750     # . epilogue
 8751     5d/pop-to-ebp
 8752     c3/return
 8753 
 8754 test-address-with-wrong-type:
 8755     # . prologue
 8756     55/push-ebp
 8757     89/<- %ebp 4/r32/esp
 8758     # setup
 8759     (clear-stream _test-input-stream)
 8760     (clear-stream $_test-input-buffered-file->buffer)
 8761     (clear-stream _test-output-stream)
 8762     (clear-stream $_test-output-buffered-file->buffer)
 8763     (clear-stream _test-error-stream)
 8764     (clear-stream $_test-error-buffered-file->buffer)
 8765     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8766     68/push 0/imm32
 8767     68/push 0/imm32
 8768     89/<- %edx 4/r32/esp
 8769     (tailor-exit-descriptor %edx 0x10)
 8770     #
 8771     (write _test-input-stream "fn foo {\n")
 8772     (write _test-input-stream "  var x: int\n")
 8773     (write _test-input-stream "  var y/eax: (addr boolean) <- address x\n")
 8774     (write _test-input-stream "}\n")
 8775     # convert
 8776     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8777     # registers except esp clobbered at this point
 8778     # restore ed
 8779     89/<- %edx 4/r32/esp
 8780     (flush _test-output-buffered-file)
 8781     (flush _test-error-buffered-file)
 8782 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8788     # check output
 8789     (check-stream-equal _test-output-stream  ""  "F - test-address-with-wrong-type: output should be empty")
 8790     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt address: output 'y' cannot hold address of 'x'"  "F - test-address-with-wrong-type: error message")
 8791     # check that stop(1) was called
 8792     (check-ints-equal *(edx+4) 2 "F - test-address-with-wrong-type: exit status")
 8793     # don't restore from ebp
 8794     81 0/subop/add %esp 8/imm32
 8795     # . epilogue
 8796     5d/pop-to-ebp
 8797     c3/return
 8798 
 8799 test-address-with-right-type-for-array:
 8800     # . prologue
 8801     55/push-ebp
 8802     89/<- %ebp 4/r32/esp
 8803     # setup
 8804     (clear-stream _test-input-stream)
 8805     (clear-stream $_test-input-buffered-file->buffer)
 8806     (clear-stream _test-output-stream)
 8807     (clear-stream $_test-output-buffered-file->buffer)
 8808     #
 8809     (write _test-input-stream "fn foo {\n")
 8810     (write _test-input-stream "  var x: (array int 3)\n")
 8811     (write _test-input-stream "  var y/eax: (addr array int) <- address x\n")
 8812     (write _test-input-stream "}\n")
 8813     # convert
 8814     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 8815     (flush _test-output-buffered-file)
 8816 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8822     # no error
 8823     (check-next-stream-line-equal _test-error-stream  ""  "F - test-address-with-right-type-for-array: error message")
 8824     # don't bother checking output
 8825     # . epilogue
 8826     89/<- %esp 5/r32/ebp
 8827     5d/pop-to-ebp
 8828     c3/return
 8829 
 8830 test-address-with-right-type-for-stream:
 8831     # . prologue
 8832     55/push-ebp
 8833     89/<- %ebp 4/r32/esp
 8834     # setup
 8835     (clear-stream _test-input-stream)
 8836     (clear-stream $_test-input-buffered-file->buffer)
 8837     (clear-stream _test-output-stream)
 8838     (clear-stream $_test-output-buffered-file->buffer)
 8839     #
 8840     (write _test-input-stream "fn foo {\n")
 8841     (write _test-input-stream "  var x: (stream int 3)\n")
 8842     (write _test-input-stream "  var y/eax: (addr stream int) <- address x\n")
 8843     (write _test-input-stream "}\n")
 8844     # convert
 8845     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 8846     (flush _test-output-buffered-file)
 8847 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8853     # no error
 8854     (check-next-stream-line-equal _test-error-stream  ""  "F - test-address-with-right-type-for-stream: error message")
 8855     # don't bother checking output
 8856     # . epilogue
 8857     89/<- %esp 5/r32/ebp
 8858     5d/pop-to-ebp
 8859     c3/return
 8860 
 8861 test-get-with-wrong-field:
 8862     # . prologue
 8863     55/push-ebp
 8864     89/<- %ebp 4/r32/esp
 8865     # setup
 8866     (clear-stream _test-input-stream)
 8867     (clear-stream $_test-input-buffered-file->buffer)
 8868     (clear-stream _test-output-stream)
 8869     (clear-stream $_test-output-buffered-file->buffer)
 8870     (clear-stream _test-error-stream)
 8871     (clear-stream $_test-error-buffered-file->buffer)
 8872     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8873     68/push 0/imm32
 8874     68/push 0/imm32
 8875     89/<- %edx 4/r32/esp
 8876     (tailor-exit-descriptor %edx 0x10)
 8877     #
 8878     (write _test-input-stream "fn foo {\n")
 8879     (write _test-input-stream "  var a: t\n")
 8880     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 8881     (write _test-input-stream "}\n")
 8882     (write _test-input-stream "type t {\n")
 8883     (write _test-input-stream "  x: int\n")
 8884     (write _test-input-stream "}\n")
 8885     # convert
 8886     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8887     # registers except esp clobbered at this point
 8888     # restore ed
 8889     89/<- %edx 4/r32/esp
 8890     (flush _test-output-buffered-file)
 8891     (flush _test-error-buffered-file)
 8892 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8898     # check output
 8899     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-field: output should be empty")
 8900     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt get: type 't' has no member called 'y'"  "F - test-get-with-wrong-field: error message")
 8901     # check that stop(1) was called
 8902     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-field: exit status")
 8903     # don't restore from ebp
 8904     81 0/subop/add %esp 8/imm32
 8905     # . epilogue
 8906     5d/pop-to-ebp
 8907     c3/return
 8908 
 8909 test-get-with-wrong-base-type:
 8910     # . prologue
 8911     55/push-ebp
 8912     89/<- %ebp 4/r32/esp
 8913     # setup
 8914     (clear-stream _test-input-stream)
 8915     (clear-stream $_test-input-buffered-file->buffer)
 8916     (clear-stream _test-output-stream)
 8917     (clear-stream $_test-output-buffered-file->buffer)
 8918     (clear-stream _test-error-stream)
 8919     (clear-stream $_test-error-buffered-file->buffer)
 8920     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8921     68/push 0/imm32
 8922     68/push 0/imm32
 8923     89/<- %edx 4/r32/esp
 8924     (tailor-exit-descriptor %edx 0x10)
 8925     #
 8926     (write _test-input-stream "fn foo {\n")
 8927     (write _test-input-stream "  var a: int\n")
 8928     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 8929     (write _test-input-stream "}\n")
 8930     # convert
 8931     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8932     # registers except esp clobbered at this point
 8933     # restore ed
 8934     89/<- %edx 4/r32/esp
 8935     (flush _test-output-buffered-file)
 8936     (flush _test-error-buffered-file)
 8937 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8943     # check output
 8944     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-base-type: output should be empty")
 8945     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt get: var 'a' must have a 'type' definition"  "F - test-get-with-wrong-base-type: error message")
 8946     # check that stop(1) was called
 8947     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-base-type: exit status")
 8948     # don't restore from ebp
 8949     81 0/subop/add %esp 8/imm32
 8950     # . epilogue
 8951     5d/pop-to-ebp
 8952     c3/return
 8953 
 8954 test-get-with-wrong-base-type-2:
 8955     # . prologue
 8956     55/push-ebp
 8957     89/<- %ebp 4/r32/esp
 8958     # setup
 8959     (clear-stream _test-input-stream)
 8960     (clear-stream $_test-input-buffered-file->buffer)
 8961     (clear-stream _test-output-stream)
 8962     (clear-stream $_test-output-buffered-file->buffer)
 8963     (clear-stream _test-error-stream)
 8964     (clear-stream $_test-error-buffered-file->buffer)
 8965     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 8966     68/push 0/imm32
 8967     68/push 0/imm32
 8968     89/<- %edx 4/r32/esp
 8969     (tailor-exit-descriptor %edx 0x10)
 8970     #
 8971     (write _test-input-stream "fn foo {\n")
 8972     (write _test-input-stream "  var a: (addr t)\n")
 8973     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 8974     (write _test-input-stream "}\n")
 8975     (write _test-input-stream "type t {\n")
 8976     (write _test-input-stream "  x: int\n")
 8977     (write _test-input-stream "}\n")
 8978     # convert
 8979     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 8980     # registers except esp clobbered at this point
 8981     # restore ed
 8982     89/<- %edx 4/r32/esp
 8983     (flush _test-output-buffered-file)
 8984     (flush _test-error-buffered-file)
 8985 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 8991     # check output
 8992     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-base-type-2: output should be empty")
 8993     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt get: var 'a' is an 'addr' type, and so must live in a register"  "F - test-get-with-wrong-base-type-2: error message")
 8994     # check that stop(1) was called
 8995     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-base-type-2: exit status")
 8996     # don't restore from ebp
 8997     81 0/subop/add %esp 8/imm32
 8998     # . epilogue
 8999     5d/pop-to-ebp
 9000     c3/return
 9001 
 9002 test-get-with-wrong-base-type-3:
 9003     # . prologue
 9004     55/push-ebp
 9005     89/<- %ebp 4/r32/esp
 9006     # setup
 9007     (clear-stream _test-input-stream)
 9008     (clear-stream $_test-input-buffered-file->buffer)
 9009     (clear-stream _test-output-stream)
 9010     (clear-stream $_test-output-buffered-file->buffer)
 9011     (clear-stream _test-error-stream)
 9012     (clear-stream $_test-error-buffered-file->buffer)
 9013     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9014     68/push 0/imm32
 9015     68/push 0/imm32
 9016     89/<- %edx 4/r32/esp
 9017     (tailor-exit-descriptor %edx 0x10)
 9018     #
 9019     (write _test-input-stream "fn foo {\n")
 9020     (write _test-input-stream "  var a: (handle int)\n")
 9021     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
 9022     (write _test-input-stream "}\n")
 9023     # convert
 9024     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9025     # registers except esp clobbered at this point
 9026     # restore ed
 9027     89/<- %edx 4/r32/esp
 9028     (flush _test-output-buffered-file)
 9029     (flush _test-error-buffered-file)
 9030 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9036     # check output
 9037     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-base-type-3: output should be empty")
 9038     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt get: var 'a' must have a 'type' definition"  "F - test-get-with-wrong-base-type-3: error message")
 9039     # check that stop(1) was called
 9040     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-base-type-3: exit status")
 9041     # don't restore from ebp
 9042     81 0/subop/add %esp 8/imm32
 9043     # . epilogue
 9044     5d/pop-to-ebp
 9045     c3/return
 9046 
 9047 test-get-with-wrong-offset-type:
 9048     # . prologue
 9049     55/push-ebp
 9050     89/<- %ebp 4/r32/esp
 9051     # setup
 9052     (clear-stream _test-input-stream)
 9053     (clear-stream $_test-input-buffered-file->buffer)
 9054     (clear-stream _test-output-stream)
 9055     (clear-stream $_test-output-buffered-file->buffer)
 9056     (clear-stream _test-error-stream)
 9057     (clear-stream $_test-error-buffered-file->buffer)
 9058     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9059     68/push 0/imm32
 9060     68/push 0/imm32
 9061     89/<- %edx 4/r32/esp
 9062     (tailor-exit-descriptor %edx 0x10)
 9063     #
 9064     (write _test-input-stream "fn foo {\n")
 9065     (write _test-input-stream "  var a: t\n")
 9066     (write _test-input-stream "  var b: int\n")
 9067     (write _test-input-stream "  var c/ecx: (addr int) <- get a, b\n")
 9068     (write _test-input-stream "}\n")
 9069     (write _test-input-stream "type t {\n")
 9070     (write _test-input-stream "  x: int\n")
 9071     (write _test-input-stream "}\n")
 9072     # convert
 9073     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9074     # registers except esp clobbered at this point
 9075     # restore ed
 9076     89/<- %edx 4/r32/esp
 9077     (flush _test-output-buffered-file)
 9078     (flush _test-error-buffered-file)
 9079 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9085     # check output
 9086     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-offset-type: output should be empty")
 9087     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt get: type 't' has no member called 'b'"  "F - test-get-with-wrong-offset-type: error message")
 9088     # check that stop(1) was called
 9089     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-offset-type: exit status")
 9090     # don't restore from ebp
 9091     81 0/subop/add %esp 8/imm32
 9092     # . epilogue
 9093     5d/pop-to-ebp
 9094     c3/return
 9095 
 9096 test-get-with-wrong-output-type:
 9097     # . prologue
 9098     55/push-ebp
 9099     89/<- %ebp 4/r32/esp
 9100     # setup
 9101     (clear-stream _test-input-stream)
 9102     (clear-stream $_test-input-buffered-file->buffer)
 9103     (clear-stream _test-output-stream)
 9104     (clear-stream $_test-output-buffered-file->buffer)
 9105     (clear-stream _test-error-stream)
 9106     (clear-stream $_test-error-buffered-file->buffer)
 9107     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9108     68/push 0/imm32
 9109     68/push 0/imm32
 9110     89/<- %edx 4/r32/esp
 9111     (tailor-exit-descriptor %edx 0x10)
 9112     #
 9113     (write _test-input-stream "fn foo {\n")
 9114     (write _test-input-stream "  var a: t\n")
 9115     (write _test-input-stream "  var c: (addr int)\n")
 9116     (write _test-input-stream "  c <- get a, x\n")
 9117     (write _test-input-stream "}\n")
 9118     (write _test-input-stream "type t {\n")
 9119     (write _test-input-stream "  x: int\n")
 9120     (write _test-input-stream "}\n")
 9121     # convert
 9122     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9123     # registers except esp clobbered at this point
 9124     # restore ed
 9125     89/<- %edx 4/r32/esp
 9126     (flush _test-output-buffered-file)
 9127     (flush _test-error-buffered-file)
 9128 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9134     # check output
 9135     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type: output should be empty")
 9136     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt get: output 'c' is not in a register"  "F - test-get-with-wrong-output-type: error message")
 9137     # check that stop(1) was called
 9138     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type: exit status")
 9139     # don't restore from ebp
 9140     81 0/subop/add %esp 8/imm32
 9141     # . epilogue
 9142     5d/pop-to-ebp
 9143     c3/return
 9144 
 9145 test-get-with-wrong-output-type-2:
 9146     # . prologue
 9147     55/push-ebp
 9148     89/<- %ebp 4/r32/esp
 9149     # setup
 9150     (clear-stream _test-input-stream)
 9151     (clear-stream $_test-input-buffered-file->buffer)
 9152     (clear-stream _test-output-stream)
 9153     (clear-stream $_test-output-buffered-file->buffer)
 9154     (clear-stream _test-error-stream)
 9155     (clear-stream $_test-error-buffered-file->buffer)
 9156     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9157     68/push 0/imm32
 9158     68/push 0/imm32
 9159     89/<- %edx 4/r32/esp
 9160     (tailor-exit-descriptor %edx 0x10)
 9161     #
 9162     (write _test-input-stream "fn foo {\n")
 9163     (write _test-input-stream "  var a: t\n")
 9164     (write _test-input-stream "  var c/ecx: int <- get a, x\n")
 9165     (write _test-input-stream "}\n")
 9166     (write _test-input-stream "type t {\n")
 9167     (write _test-input-stream "  x: int\n")
 9168     (write _test-input-stream "}\n")
 9169     # convert
 9170     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9171     # registers except esp clobbered at this point
 9172     # restore ed
 9173     89/<- %edx 4/r32/esp
 9174     (flush _test-output-buffered-file)
 9175     (flush _test-error-buffered-file)
 9176 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9182     # check output
 9183     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type-2: output should be empty")
 9184     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt get: output must be an addr"  "F - test-get-with-wrong-output-type-2: error message")
 9185     # check that stop(1) was called
 9186     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type-2: exit status")
 9187     # don't restore from ebp
 9188     81 0/subop/add %esp 8/imm32
 9189     # . epilogue
 9190     5d/pop-to-ebp
 9191     c3/return
 9192 
 9193 test-get-with-wrong-output-type-3:
 9194     # . prologue
 9195     55/push-ebp
 9196     89/<- %ebp 4/r32/esp
 9197     # setup
 9198     (clear-stream _test-input-stream)
 9199     (clear-stream $_test-input-buffered-file->buffer)
 9200     (clear-stream _test-output-stream)
 9201     (clear-stream $_test-output-buffered-file->buffer)
 9202     (clear-stream _test-error-stream)
 9203     (clear-stream $_test-error-buffered-file->buffer)
 9204     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9205     68/push 0/imm32
 9206     68/push 0/imm32
 9207     89/<- %edx 4/r32/esp
 9208     (tailor-exit-descriptor %edx 0x10)
 9209     #
 9210     (write _test-input-stream "fn foo {\n")
 9211     (write _test-input-stream "  var a: t\n")
 9212     (write _test-input-stream "  var c/ecx: (array int) <- get a, x\n")
 9213     (write _test-input-stream "}\n")
 9214     (write _test-input-stream "type t {\n")
 9215     (write _test-input-stream "  x: int\n")
 9216     (write _test-input-stream "}\n")
 9217     # convert
 9218     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9219     # registers except esp clobbered at this point
 9220     # restore ed
 9221     89/<- %edx 4/r32/esp
 9222     (flush _test-output-buffered-file)
 9223     (flush _test-error-buffered-file)
 9224 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9230     # check output
 9231     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type-3: output should be empty")
 9232     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt get: output must be an addr"  "F - test-get-with-wrong-output-type-3: error message")
 9233     # check that stop(1) was called
 9234     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type-3: exit status")
 9235     # don't restore from ebp
 9236     81 0/subop/add %esp 8/imm32
 9237     # . epilogue
 9238     5d/pop-to-ebp
 9239     c3/return
 9240 
 9241 test-get-with-wrong-output-type-4:
 9242     # . prologue
 9243     55/push-ebp
 9244     89/<- %ebp 4/r32/esp
 9245     # setup
 9246     (clear-stream _test-input-stream)
 9247     (clear-stream $_test-input-buffered-file->buffer)
 9248     (clear-stream _test-output-stream)
 9249     (clear-stream $_test-output-buffered-file->buffer)
 9250     (clear-stream _test-error-stream)
 9251     (clear-stream $_test-error-buffered-file->buffer)
 9252     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9253     68/push 0/imm32
 9254     68/push 0/imm32
 9255     89/<- %edx 4/r32/esp
 9256     (tailor-exit-descriptor %edx 0x10)
 9257     #
 9258     (write _test-input-stream "fn foo {\n")
 9259     (write _test-input-stream "  var a: t\n")
 9260     (write _test-input-stream "  var c/ecx: (addr boolean) <- get a, x\n")
 9261     (write _test-input-stream "}\n")
 9262     (write _test-input-stream "type t {\n")
 9263     (write _test-input-stream "  x: int\n")
 9264     (write _test-input-stream "}\n")
 9265     # convert
 9266     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9267     # registers except esp clobbered at this point
 9268     # restore ed
 9269     89/<- %edx 4/r32/esp
 9270     (flush _test-output-buffered-file)
 9271     (flush _test-error-buffered-file)
 9272 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9278     # check output
 9279     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type-4: output should be empty")
 9280     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt get: wrong output type for member 'x' of type 't'"  "F - test-get-with-wrong-output-type-4: error message")
 9281     # check that stop(1) was called
 9282     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type-4: exit status")
 9283     # don't restore from ebp
 9284     81 0/subop/add %esp 8/imm32
 9285     # . epilogue
 9286     5d/pop-to-ebp
 9287     c3/return
 9288 
 9289 test-get-with-wrong-output-type-5:
 9290     # . prologue
 9291     55/push-ebp
 9292     89/<- %ebp 4/r32/esp
 9293     # setup
 9294     (clear-stream _test-input-stream)
 9295     (clear-stream $_test-input-buffered-file->buffer)
 9296     (clear-stream _test-output-stream)
 9297     (clear-stream $_test-output-buffered-file->buffer)
 9298     #
 9299     (write _test-input-stream "fn foo {\n")
 9300     (write _test-input-stream "  var a: t\n")
 9301     (write _test-input-stream "  var c/ecx: (addr handle int) <- get a, x\n")
 9302     (write _test-input-stream "}\n")
 9303     (write _test-input-stream "type t {\n")
 9304     (write _test-input-stream "  x: (handle int)\n")
 9305     (write _test-input-stream "}\n")
 9306     # convert
 9307     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 9308     (flush _test-output-buffered-file)
 9309     # no errors
 9310     # . epilogue
 9311     89/<- %esp 5/r32/ebp
 9312     5d/pop-to-ebp
 9313     c3/return
 9314 
 9315 test-get-with-too-few-inouts:
 9316     # . prologue
 9317     55/push-ebp
 9318     89/<- %ebp 4/r32/esp
 9319     # setup
 9320     (clear-stream _test-input-stream)
 9321     (clear-stream $_test-input-buffered-file->buffer)
 9322     (clear-stream _test-output-stream)
 9323     (clear-stream $_test-output-buffered-file->buffer)
 9324     (clear-stream _test-error-stream)
 9325     (clear-stream $_test-error-buffered-file->buffer)
 9326     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9327     68/push 0/imm32
 9328     68/push 0/imm32
 9329     89/<- %edx 4/r32/esp
 9330     (tailor-exit-descriptor %edx 0x10)
 9331     #
 9332     (write _test-input-stream "fn foo {\n")
 9333     (write _test-input-stream "  var a: t\n")
 9334     (write _test-input-stream "  var c/ecx: (addr int) <- get a\n")
 9335     (write _test-input-stream "}\n")
 9336     (write _test-input-stream "type t {\n")
 9337     (write _test-input-stream "  x: int\n")
 9338     (write _test-input-stream "}\n")
 9339     # convert
 9340     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9341     # registers except esp clobbered at this point
 9342     # restore ed
 9343     89/<- %edx 4/r32/esp
 9344     (flush _test-output-buffered-file)
 9345     (flush _test-error-buffered-file)
 9346 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9352     # check output
 9353     (check-stream-equal _test-output-stream  ""  "F - test-get-with-too-few-inouts: output should be empty")
 9354     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt get: too few inouts (2 required)"  "F - test-get-with-too-few-inouts: error message")
 9355     # check that stop(1) was called
 9356     (check-ints-equal *(edx+4) 2 "F - test-get-with-too-few-inouts: exit status")
 9357     # don't restore from ebp
 9358     81 0/subop/add %esp 8/imm32
 9359     # . epilogue
 9360     5d/pop-to-ebp
 9361     c3/return
 9362 
 9363 test-get-with-too-many-inouts:
 9364     # . prologue
 9365     55/push-ebp
 9366     89/<- %ebp 4/r32/esp
 9367     # setup
 9368     (clear-stream _test-input-stream)
 9369     (clear-stream $_test-input-buffered-file->buffer)
 9370     (clear-stream _test-output-stream)
 9371     (clear-stream $_test-output-buffered-file->buffer)
 9372     (clear-stream _test-error-stream)
 9373     (clear-stream $_test-error-buffered-file->buffer)
 9374     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9375     68/push 0/imm32
 9376     68/push 0/imm32
 9377     89/<- %edx 4/r32/esp
 9378     (tailor-exit-descriptor %edx 0x10)
 9379     #
 9380     (write _test-input-stream "fn foo {\n")
 9381     (write _test-input-stream "  var a: t\n")
 9382     (write _test-input-stream "  var c/ecx: (addr int) <- get a, x, 0\n")
 9383     (write _test-input-stream "}\n")
 9384     (write _test-input-stream "type t {\n")
 9385     (write _test-input-stream "  x: int\n")
 9386     (write _test-input-stream "}\n")
 9387     # convert
 9388     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9389     # registers except esp clobbered at this point
 9390     # restore ed
 9391     89/<- %edx 4/r32/esp
 9392     (flush _test-output-buffered-file)
 9393     (flush _test-error-buffered-file)
 9394 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9400     # check output
 9401     (check-stream-equal _test-output-stream  ""  "F - test-get-with-too-many-inouts: output should be empty")
 9402     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt get: too many inouts (2 required)"  "F - test-get-with-too-many-inouts: error message")
 9403     # check that stop(1) was called
 9404     (check-ints-equal *(edx+4) 2 "F - test-get-with-too-many-inouts: exit status")
 9405     # don't restore from ebp
 9406     81 0/subop/add %esp 8/imm32
 9407     # . epilogue
 9408     5d/pop-to-ebp
 9409     c3/return
 9410 
 9411 test-get-with-no-output:
 9412     # . prologue
 9413     55/push-ebp
 9414     89/<- %ebp 4/r32/esp
 9415     # setup
 9416     (clear-stream _test-input-stream)
 9417     (clear-stream $_test-input-buffered-file->buffer)
 9418     (clear-stream _test-output-stream)
 9419     (clear-stream $_test-output-buffered-file->buffer)
 9420     (clear-stream _test-error-stream)
 9421     (clear-stream $_test-error-buffered-file->buffer)
 9422     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9423     68/push 0/imm32
 9424     68/push 0/imm32
 9425     89/<- %edx 4/r32/esp
 9426     (tailor-exit-descriptor %edx 0x10)
 9427     #
 9428     (write _test-input-stream "fn foo {\n")
 9429     (write _test-input-stream "  var a: t\n")
 9430     (write _test-input-stream "  get a, x\n")
 9431     (write _test-input-stream "}\n")
 9432     (write _test-input-stream "type t {\n")
 9433     (write _test-input-stream "  x: int\n")
 9434     (write _test-input-stream "}\n")
 9435     # convert
 9436     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9437     # registers except esp clobbered at this point
 9438     # restore ed
 9439     89/<- %edx 4/r32/esp
 9440     (flush _test-output-buffered-file)
 9441     (flush _test-error-buffered-file)
 9442 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9448     # check output
 9449     (check-stream-equal _test-output-stream  ""  "F - test-get-with-no-output: output should be empty")
 9450     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt get: must have an output"  "F - test-get-with-no-output: error message")
 9451     # check that stop(1) was called
 9452     (check-ints-equal *(edx+4) 2 "F - test-get-with-no-output: exit status")
 9453     # don't restore from ebp
 9454     81 0/subop/add %esp 8/imm32
 9455     # . epilogue
 9456     5d/pop-to-ebp
 9457     c3/return
 9458 
 9459 test-get-with-too-many-outputs:
 9460     # . prologue
 9461     55/push-ebp
 9462     89/<- %ebp 4/r32/esp
 9463     # setup
 9464     (clear-stream _test-input-stream)
 9465     (clear-stream $_test-input-buffered-file->buffer)
 9466     (clear-stream _test-output-stream)
 9467     (clear-stream $_test-output-buffered-file->buffer)
 9468     (clear-stream _test-error-stream)
 9469     (clear-stream $_test-error-buffered-file->buffer)
 9470     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9471     68/push 0/imm32
 9472     68/push 0/imm32
 9473     89/<- %edx 4/r32/esp
 9474     (tailor-exit-descriptor %edx 0x10)
 9475     #
 9476     (write _test-input-stream "fn foo {\n")
 9477     (write _test-input-stream "  var a: t\n")
 9478     (write _test-input-stream "  var b: int\n")
 9479     (write _test-input-stream "  var c/eax: (addr int) <- copy 0\n")
 9480     (write _test-input-stream "  c, b <- get a, x\n")
 9481     (write _test-input-stream "}\n")
 9482     (write _test-input-stream "type t {\n")
 9483     (write _test-input-stream "  x: int\n")
 9484     (write _test-input-stream "}\n")
 9485     # convert
 9486     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9487     # registers except esp clobbered at this point
 9488     # restore ed
 9489     89/<- %edx 4/r32/esp
 9490     (flush _test-output-buffered-file)
 9491     (flush _test-error-buffered-file)
 9492 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9498     # check output
 9499     (check-stream-equal _test-output-stream  ""  "F - test-get-with-too-many-outputs: output should be empty")
 9500     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt get: too many outputs (1 required)"  "F - test-get-with-too-many-outputs: error message")
 9501     # check that stop(1) was called
 9502     (check-ints-equal *(edx+4) 2 "F - test-get-with-too-many-outputs: exit status")
 9503     # don't restore from ebp
 9504     81 0/subop/add %esp 8/imm32
 9505     # . epilogue
 9506     5d/pop-to-ebp
 9507     c3/return
 9508 
 9509 test-convert-array-of-user-defined-types:
 9510     # . prologue
 9511     55/push-ebp
 9512     89/<- %ebp 4/r32/esp
 9513     # setup
 9514     (clear-stream _test-input-stream)
 9515     (clear-stream $_test-input-buffered-file->buffer)
 9516     (clear-stream _test-output-stream)
 9517     (clear-stream $_test-output-buffered-file->buffer)
 9518     #
 9519     (write _test-input-stream "type t {\n")  # each t is 8 bytes, which is a power of 2
 9520     (write _test-input-stream "  x: int\n")
 9521     (write _test-input-stream "  y: int\n")
 9522     (write _test-input-stream "}\n")
 9523     (write _test-input-stream "fn foo {\n")
 9524     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
 9525     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
 9526     (write _test-input-stream "  var x/eax: (addr t) <- index arr, idx\n")
 9527     (write _test-input-stream "}\n")
 9528     # convert
 9529     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 9530     (flush _test-output-buffered-file)
 9531 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9537     # check output
 9538     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-array-of-user-defined-types/0")
 9539     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-array-of-user-defined-types/1")
 9540     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-array-of-user-defined-types/2")
 9541     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-array-of-user-defined-types/3")
 9542     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-array-of-user-defined-types/4")
 9543     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-array-of-user-defined-types/5")
 9544     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-array-of-user-defined-types/6")
 9545     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-array-of-user-defined-types/7")
 9546     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-array-of-user-defined-types/8")
 9547     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-array-of-user-defined-types/9")
 9548     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds %ecx 0x00000008 *eax \"foo\" \"arr\")"  "F - test-convert-array-of-user-defined-types/10")
 9549     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx<<0x00000003 + 4) 0x00000000/r32"  "F - test-convert-array-of-user-defined-types/11")
 9550     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-array-of-user-defined-types/12")
 9551     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-array-of-user-defined-types/13")
 9552     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-array-of-user-defined-types/14")
 9553     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-array-of-user-defined-types/15")
 9554     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-array-of-user-defined-types/16")
 9555     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-array-of-user-defined-types/17")
 9556     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-array-of-user-defined-types/18")
 9557     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-array-of-user-defined-types/19")
 9558     # . epilogue
 9559     89/<- %esp 5/r32/ebp
 9560     5d/pop-to-ebp
 9561     c3/return
 9562 
 9563 test-convert-length-of-array-of-user-defined-types-to-eax:
 9564     # . prologue
 9565     55/push-ebp
 9566     89/<- %ebp 4/r32/esp
 9567     # setup
 9568     (clear-stream _test-input-stream)
 9569     (clear-stream $_test-input-buffered-file->buffer)
 9570     (clear-stream _test-output-stream)
 9571     (clear-stream $_test-output-buffered-file->buffer)
 9572     #
 9573     (write _test-input-stream "type t {\n")  # size = 12, which is not a power of 2
 9574     (write _test-input-stream "  x: int\n")
 9575     (write _test-input-stream "  y: int\n")
 9576     (write _test-input-stream "  z: int\n")
 9577     (write _test-input-stream "}\n")
 9578     (write _test-input-stream "fn foo {\n")
 9579     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
 9580     (write _test-input-stream "  var x/eax: int <- length arr\n")
 9581     (write _test-input-stream "}\n")
 9582     # convert
 9583     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 9584     (flush _test-output-buffered-file)
 9585 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9591     # check output
 9592     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types-to-eax/0")
 9593     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types-to-eax/1")
 9594     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types-to-eax/2")
 9595     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array-of-user-defined-types-to-eax/3")
 9596     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types-to-eax/4")
 9597     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types-to-eax/5")
 9598     # var arr
 9599     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array-of-user-defined-types-to-eax/6")
 9600     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"  "F - test-convert-length-of-array-of-user-defined-types-to-eax/7")
 9601     # length instruction
 9602     (check-next-stream-line-equal _test-output-stream "    51/push-ecx"         "F - test-convert-length-of-array-of-user-defined-types-to-eax/8")
 9603     (check-next-stream-line-equal _test-output-stream "    52/push-edx"         "F - test-convert-length-of-array-of-user-defined-types-to-eax/9")
 9604     (check-next-stream-line-equal _test-output-stream "    8b/-> *eax 0x00000000/r32"  "F - test-convert-length-of-array-of-user-defined-types-to-eax/10")
 9605     (check-next-stream-line-equal _test-output-stream "    31/xor %edx 2/r32/edx"  "F - test-convert-length-of-array-of-user-defined-types-to-eax/11")
 9606     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0x0000000c/imm32"  "F - test-convert-length-of-array-of-user-defined-types-to-eax/12")
 9607     (check-next-stream-line-equal _test-output-stream "    f7 7/subop/idiv-eax-edx-by %ecx"  "F - test-convert-length-of-array-of-user-defined-types-to-eax/13")
 9608     (check-next-stream-line-equal _test-output-stream "    5a/pop-to-edx"       "F - test-convert-length-of-array-of-user-defined-types-to-eax/14")
 9609     (check-next-stream-line-equal _test-output-stream "    59/pop-to-ecx"       "F - test-convert-length-of-array-of-user-defined-types-to-eax/15")
 9610     # reclaim arr
 9611     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array-of-user-defined-types-to-eax/16")
 9612     #
 9613     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types-to-eax/17")
 9614     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types-to-eax/18")
 9615     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types-to-eax/19")
 9616     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array-of-user-defined-types-to-eax/20")
 9617     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array-of-user-defined-types-to-eax/21")
 9618     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types-to-eax/22")
 9619     # . epilogue
 9620     89/<- %esp 5/r32/ebp
 9621     5d/pop-to-ebp
 9622     c3/return
 9623 
 9624 test-convert-length-of-array-of-user-defined-types-to-ecx:
 9625     # . prologue
 9626     55/push-ebp
 9627     89/<- %ebp 4/r32/esp
 9628     # setup
 9629     (clear-stream _test-input-stream)
 9630     (clear-stream $_test-input-buffered-file->buffer)
 9631     (clear-stream _test-output-stream)
 9632     (clear-stream $_test-output-buffered-file->buffer)
 9633     #
 9634     (write _test-input-stream "type t {\n")  # size = 12, which is not a power of 2
 9635     (write _test-input-stream "  x: int\n")
 9636     (write _test-input-stream "  y: int\n")
 9637     (write _test-input-stream "  z: int\n")
 9638     (write _test-input-stream "}\n")
 9639     (write _test-input-stream "fn foo {\n")
 9640     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
 9641     (write _test-input-stream "  var x/ecx: int <- length arr\n")
 9642     (write _test-input-stream "}\n")
 9643     # convert
 9644     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 9645     (flush _test-output-buffered-file)
 9646 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9652     # check output
 9653     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types-to-ecx/0")
 9654     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types-to-ecx/1")
 9655     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types-to-ecx/2")
 9656     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array-of-user-defined-types-to-ecx/3")
 9657     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types-to-ecx/4")
 9658     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types-to-ecx/5")
 9659     # var a
 9660     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array-of-user-defined-types-to-ecx/6")
 9661     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"  "F - test-convert-length-of-array-of-user-defined-types-to-ecx/7")
 9662     # var x
 9663     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-length-of-array-of-user-defined-types-to-ecx/8")
 9664     # length instruction
 9665     (check-next-stream-line-equal _test-output-stream "    50/push-eax"         "F - test-convert-length-of-array-of-user-defined-types-to-ecx/9")
 9666     (check-next-stream-line-equal _test-output-stream "    52/push-edx"         "F - test-convert-length-of-array-of-user-defined-types-to-ecx/10")
 9667     (check-next-stream-line-equal _test-output-stream "    8b/-> *eax 0x00000000/r32"  "F - test-convert-length-of-array-of-user-defined-types-to-ecx/11")
 9668     (check-next-stream-line-equal _test-output-stream "    31/xor %edx 2/r32/edx"  "F - test-convert-length-of-array-of-user-defined-types-to-ecx/12")
 9669     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0x0000000c/imm32"  "F - test-convert-length-of-array-of-user-defined-types-to-ecx/13")
 9670     (check-next-stream-line-equal _test-output-stream "    f7 7/subop/idiv-eax-edx-by %ecx"  "F - test-convert-length-of-array-of-user-defined-types-to-ecx/14")
 9671     (check-next-stream-line-equal _test-output-stream "    89/<- %ecx 0/r32/eax"  "F - test-convert-length-of-array-of-user-defined-types-to-ecx/15")
 9672     (check-next-stream-line-equal _test-output-stream "    5a/pop-to-edx"       "F - test-convert-length-of-array-of-user-defined-types-to-ecx/16")
 9673     (check-next-stream-line-equal _test-output-stream "    58/pop-to-eax"       "F - test-convert-length-of-array-of-user-defined-types-to-ecx/17")
 9674     # reclaim x
 9675     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"  "F - test-convert-length-of-array-of-user-defined-types-to-ecx/18")
 9676     # reclaim a
 9677     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array-of-user-defined-types-to-ecx/19")
 9678     #
 9679     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types-to-ecx/20")
 9680     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types-to-ecx/21")
 9681     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types-to-ecx/22")
 9682     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array-of-user-defined-types-to-ecx/23")
 9683     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array-of-user-defined-types-to-ecx/24")
 9684     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types-to-ecx/25")
 9685     # . epilogue
 9686     89/<- %esp 5/r32/ebp
 9687     5d/pop-to-ebp
 9688     c3/return
 9689 
 9690 test-convert-length-of-array-of-user-defined-types-to-edx:
 9691     # . prologue
 9692     55/push-ebp
 9693     89/<- %ebp 4/r32/esp
 9694     # setup
 9695     (clear-stream _test-input-stream)
 9696     (clear-stream $_test-input-buffered-file->buffer)
 9697     (clear-stream _test-output-stream)
 9698     (clear-stream $_test-output-buffered-file->buffer)
 9699     #
 9700     (write _test-input-stream "type t {\n")  # size = 12, which is not a power of 2
 9701     (write _test-input-stream "  x: int\n")
 9702     (write _test-input-stream "  y: int\n")
 9703     (write _test-input-stream "  z: int\n")
 9704     (write _test-input-stream "}\n")
 9705     (write _test-input-stream "fn foo {\n")
 9706     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
 9707     (write _test-input-stream "  var x/edx: int <- length arr\n")
 9708     (write _test-input-stream "}\n")
 9709     # convert
 9710     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 9711     (flush _test-output-buffered-file)
 9712 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9718     # check output
 9719     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types-to-edx/0")
 9720     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types-to-edx/1")
 9721     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types-to-edx/2")
 9722     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array-of-user-defined-types-to-edx/3")
 9723     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types-to-edx/4")
 9724     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types-to-edx/5")
 9725     # var a
 9726     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array-of-user-defined-types-to-edx/6")
 9727     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"  "F - test-convert-length-of-array-of-user-defined-types-to-edx/7")
 9728     # var x
 9729     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %edx"  "F - test-convert-length-of-array-of-user-defined-types-to-edx/8")
 9730     # length instruction
 9731     (check-next-stream-line-equal _test-output-stream "    50/push-eax"         "F - test-convert-length-of-array-of-user-defined-types-to-edx/9")
 9732     (check-next-stream-line-equal _test-output-stream "    51/push-ecx"         "F - test-convert-length-of-array-of-user-defined-types-to-edx/10")
 9733     (check-next-stream-line-equal _test-output-stream "    8b/-> *eax 0x00000000/r32"  "F - test-convert-length-of-array-of-user-defined-types-to-edx/11")
 9734     (check-next-stream-line-equal _test-output-stream "    31/xor %edx 2/r32/edx"  "F - test-convert-length-of-array-of-user-defined-types-to-edx/12")
 9735     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0x0000000c/imm32"  "F - test-convert-length-of-array-of-user-defined-types-to-edx/13")
 9736     (check-next-stream-line-equal _test-output-stream "    f7 7/subop/idiv-eax-edx-by %ecx"  "F - test-convert-length-of-array-of-user-defined-types-to-edx/14")
 9737     (check-next-stream-line-equal _test-output-stream "    89/<- %edx 0/r32/eax"  "F - test-convert-length-of-array-of-user-defined-types-to-edx/15")
 9738     (check-next-stream-line-equal _test-output-stream "    59/pop-to-ecx"       "F - test-convert-length-of-array-of-user-defined-types-to-edx/16")
 9739     (check-next-stream-line-equal _test-output-stream "    58/pop-to-eax"       "F - test-convert-length-of-array-of-user-defined-types-to-edx/17")
 9740     # reclaim x
 9741     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %edx"  "F - test-convert-length-of-array-of-user-defined-types-to-edx/18")
 9742     # reclaim a
 9743     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array-of-user-defined-types-to-edx/19")
 9744     #
 9745     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types-to-edx/20")
 9746     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types-to-edx/21")
 9747     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types-to-edx/22")
 9748     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array-of-user-defined-types-to-edx/23")
 9749     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array-of-user-defined-types-to-edx/24")
 9750     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types-to-edx/25")
 9751     # . epilogue
 9752     89/<- %esp 5/r32/ebp
 9753     5d/pop-to-ebp
 9754     c3/return
 9755 
 9756 test-convert-length-of-array-of-user-defined-types:
 9757     # . prologue
 9758     55/push-ebp
 9759     89/<- %ebp 4/r32/esp
 9760     # setup
 9761     (clear-stream _test-input-stream)
 9762     (clear-stream $_test-input-buffered-file->buffer)
 9763     (clear-stream _test-output-stream)
 9764     (clear-stream $_test-output-buffered-file->buffer)
 9765     #
 9766     (write _test-input-stream "type t {\n")  # each t is 8 bytes, which is a power of 2
 9767     (write _test-input-stream "  x: int\n")
 9768     (write _test-input-stream "  y: int\n")
 9769     (write _test-input-stream "  z: int\n")
 9770     (write _test-input-stream "}\n")
 9771     (write _test-input-stream "fn foo {\n")
 9772     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
 9773     (write _test-input-stream "  var x/ebx: int <- length arr\n")
 9774     (write _test-input-stream "}\n")
 9775     # convert
 9776     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
 9777     (flush _test-output-buffered-file)
 9778 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9784     # check output
 9785     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types/0")
 9786     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types/1")
 9787     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types/2")
 9788     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array-of-user-defined-types/3")
 9789     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types/4")
 9790     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types/5")
 9791     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array-of-user-defined-types/6")
 9792     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"  "F - test-convert-length-of-array-of-user-defined-types/7")
 9793     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ebx"  "F - test-convert-length-of-array-of-user-defined-types/8")
 9794     (check-next-stream-line-equal _test-output-stream "    50/push-eax"         "F - test-convert-length-of-array-of-user-defined-types/9")
 9795     (check-next-stream-line-equal _test-output-stream "    51/push-ecx"         "F - test-convert-length-of-array-of-user-defined-types/10")
 9796     (check-next-stream-line-equal _test-output-stream "    52/push-edx"         "F - test-convert-length-of-array-of-user-defined-types/11")
 9797     (check-next-stream-line-equal _test-output-stream "    8b/-> *eax 0x00000000/r32"  "F - test-convert-length-of-array-of-user-defined-types/12")
 9798     (check-next-stream-line-equal _test-output-stream "    31/xor %edx 2/r32/edx"  "F - test-convert-length-of-array-of-user-defined-types/13")
 9799     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0x0000000c/imm32"  "F - test-convert-length-of-array-of-user-defined-types/14")
 9800     (check-next-stream-line-equal _test-output-stream "    f7 7/subop/idiv-eax-edx-by %ecx"  "F - test-convert-length-of-array-of-user-defined-types/15")
 9801     (check-next-stream-line-equal _test-output-stream "    89/<- %ebx 0/r32/eax"  "F - test-convert-length-of-array-of-user-defined-types/16")
 9802     (check-next-stream-line-equal _test-output-stream "    5a/pop-to-edx"       "F - test-convert-length-of-array-of-user-defined-types/17")
 9803     (check-next-stream-line-equal _test-output-stream "    59/pop-to-ecx"       "F - test-convert-length-of-array-of-user-defined-types/18")
 9804     (check-next-stream-line-equal _test-output-stream "    58/pop-to-eax"       "F - test-convert-length-of-array-of-user-defined-types/19")
 9805     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ebx"  "F - test-convert-length-of-array-of-user-defined-types/20")
 9806     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array-of-user-defined-types/21")
 9807     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types/22")
 9808     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types/23")
 9809     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types/24")
 9810     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array-of-user-defined-types/25")
 9811     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array-of-user-defined-types/26")
 9812     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types/27")
 9813     # . epilogue
 9814     89/<- %esp 5/r32/ebp
 9815     5d/pop-to-ebp
 9816     c3/return
 9817 
 9818 test-index-with-non-array-atom-base-type:
 9819     # . prologue
 9820     55/push-ebp
 9821     89/<- %ebp 4/r32/esp
 9822     # setup
 9823     (clear-stream _test-input-stream)
 9824     (clear-stream $_test-input-buffered-file->buffer)
 9825     (clear-stream _test-output-stream)
 9826     (clear-stream $_test-output-buffered-file->buffer)
 9827     (clear-stream _test-error-stream)
 9828     (clear-stream $_test-error-buffered-file->buffer)
 9829     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9830     68/push 0/imm32
 9831     68/push 0/imm32
 9832     89/<- %edx 4/r32/esp
 9833     (tailor-exit-descriptor %edx 0x10)
 9834     #
 9835     (write _test-input-stream "fn foo {\n")
 9836     (write _test-input-stream "  var a: int\n")
 9837     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
 9838     (write _test-input-stream "}\n")
 9839     # convert
 9840     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9841     # registers except esp clobbered at this point
 9842     # restore ed
 9843     89/<- %edx 4/r32/esp
 9844     (flush _test-output-buffered-file)
 9845     (flush _test-error-buffered-file)
 9846 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9852     # check output
 9853     (check-stream-equal _test-output-stream  ""  "F - test-index-with-non-array-atom-base-type: output should be empty")
 9854     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: var 'a' is not an array"  "F - test-index-with-non-array-atom-base-type: error message")
 9855     # check that stop(1) was called
 9856     (check-ints-equal *(edx+4) 2 "F - test-index-with-non-array-atom-base-type: exit status")
 9857     # don't restore from ebp
 9858     81 0/subop/add %esp 8/imm32
 9859     # . epilogue
 9860     5d/pop-to-ebp
 9861     c3/return
 9862 
 9863 test-index-with-non-array-compound-base-type:
 9864     # . prologue
 9865     55/push-ebp
 9866     89/<- %ebp 4/r32/esp
 9867     # setup
 9868     (clear-stream _test-input-stream)
 9869     (clear-stream $_test-input-buffered-file->buffer)
 9870     (clear-stream _test-output-stream)
 9871     (clear-stream $_test-output-buffered-file->buffer)
 9872     (clear-stream _test-error-stream)
 9873     (clear-stream $_test-error-buffered-file->buffer)
 9874     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9875     68/push 0/imm32
 9876     68/push 0/imm32
 9877     89/<- %edx 4/r32/esp
 9878     (tailor-exit-descriptor %edx 0x10)
 9879     #
 9880     (write _test-input-stream "fn foo {\n")
 9881     (write _test-input-stream "  var a: (handle int)\n")
 9882     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
 9883     (write _test-input-stream "}\n")
 9884     # convert
 9885     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9886     # registers except esp clobbered at this point
 9887     # restore ed
 9888     89/<- %edx 4/r32/esp
 9889     (flush _test-output-buffered-file)
 9890     (flush _test-error-buffered-file)
 9891 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9897     # check output
 9898     (check-stream-equal _test-output-stream  ""  "F - test-index-with-non-array-compound-base-type: output should be empty")
 9899     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: var 'a' is not an array"  "F - test-index-with-non-array-compound-base-type: error message")
 9900     # check that stop(1) was called
 9901     (check-ints-equal *(edx+4) 2 "F - test-index-with-non-array-compound-base-type: exit status")
 9902     # don't restore from ebp
 9903     81 0/subop/add %esp 8/imm32
 9904     # . epilogue
 9905     5d/pop-to-ebp
 9906     c3/return
 9907 
 9908 test-index-with-non-array-compound-base-type-2:
 9909     # . prologue
 9910     55/push-ebp
 9911     89/<- %ebp 4/r32/esp
 9912     # setup
 9913     (clear-stream _test-input-stream)
 9914     (clear-stream $_test-input-buffered-file->buffer)
 9915     (clear-stream _test-output-stream)
 9916     (clear-stream $_test-output-buffered-file->buffer)
 9917     (clear-stream _test-error-stream)
 9918     (clear-stream $_test-error-buffered-file->buffer)
 9919     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9920     68/push 0/imm32
 9921     68/push 0/imm32
 9922     89/<- %edx 4/r32/esp
 9923     (tailor-exit-descriptor %edx 0x10)
 9924     #
 9925     (write _test-input-stream "fn foo {\n")
 9926     (write _test-input-stream "  var a: (addr int)\n")
 9927     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
 9928     (write _test-input-stream "}\n")
 9929     # convert
 9930     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9931     # registers except esp clobbered at this point
 9932     # restore ed
 9933     89/<- %edx 4/r32/esp
 9934     (flush _test-output-buffered-file)
 9935     (flush _test-error-buffered-file)
 9936 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9942     # check output
 9943     (check-stream-equal _test-output-stream  ""  "F - test-index-with-non-array-compound-base-type-2: output should be empty")
 9944     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: var 'a' is not an array"  "F - test-index-with-non-array-compound-base-type-2: error message")
 9945     # check that stop(1) was called
 9946     (check-ints-equal *(edx+4) 2 "F - test-index-with-non-array-compound-base-type-2: exit status")
 9947     # don't restore from ebp
 9948     81 0/subop/add %esp 8/imm32
 9949     # . epilogue
 9950     5d/pop-to-ebp
 9951     c3/return
 9952 
 9953 test-index-with-array-atom-base-type:
 9954     # . prologue
 9955     55/push-ebp
 9956     89/<- %ebp 4/r32/esp
 9957     # setup
 9958     (clear-stream _test-input-stream)
 9959     (clear-stream $_test-input-buffered-file->buffer)
 9960     (clear-stream _test-output-stream)
 9961     (clear-stream $_test-output-buffered-file->buffer)
 9962     (clear-stream _test-error-stream)
 9963     (clear-stream $_test-error-buffered-file->buffer)
 9964     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
 9965     68/push 0/imm32
 9966     68/push 0/imm32
 9967     89/<- %edx 4/r32/esp
 9968     (tailor-exit-descriptor %edx 0x10)
 9969     #
 9970     (write _test-input-stream "fn foo {\n")
 9971     (write _test-input-stream "  var a: array\n")
 9972     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
 9973     (write _test-input-stream "}\n")
 9974     # convert
 9975     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
 9976     # registers except esp clobbered at this point
 9977     # restore ed
 9978     89/<- %edx 4/r32/esp
 9979     (flush _test-output-buffered-file)
 9980     (flush _test-error-buffered-file)
 9981 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 9987     # check output
 9988     (check-stream-equal _test-output-stream  ""  "F - test-index-with-array-atom-base-type: output should be empty")
 9989     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: array 'a' must specify the type of its elements"  "F - test-index-with-array-atom-base-type: error message")
 9990     # check that stop(1) was called
 9991     (check-ints-equal *(edx+4) 2 "F - test-index-with-array-atom-base-type: exit status")
 9992     # don't restore from ebp
 9993     81 0/subop/add %esp 8/imm32
 9994     # . epilogue
 9995     5d/pop-to-ebp
 9996     c3/return
 9997 
 9998 test-index-with-addr-base-on-stack:
 9999     # . prologue
10000     55/push-ebp
10001     89/<- %ebp 4/r32/esp
10002     # setup
10003     (clear-stream _test-input-stream)
10004     (clear-stream $_test-input-buffered-file->buffer)
10005     (clear-stream _test-output-stream)
10006     (clear-stream $_test-output-buffered-file->buffer)
10007     (clear-stream _test-error-stream)
10008     (clear-stream $_test-error-buffered-file->buffer)
10009     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10010     68/push 0/imm32
10011     68/push 0/imm32
10012     89/<- %edx 4/r32/esp
10013     (tailor-exit-descriptor %edx 0x10)
10014     #
10015     (write _test-input-stream "fn foo {\n")
10016     (write _test-input-stream "  var a: (addr array int)\n")
10017     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
10018     (write _test-input-stream "}\n")
10019     # convert
10020     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10021     # registers except esp clobbered at this point
10022     # restore ed
10023     89/<- %edx 4/r32/esp
10024     (flush _test-output-buffered-file)
10025     (flush _test-error-buffered-file)
10026 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10032     # check output
10033     (check-stream-equal _test-output-stream  ""  "F - test-index-with-addr-base-on-stack: output should be empty")
10034     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: var 'a' is an addr to an array, and so must live in a register"  "F - test-index-with-addr-base-on-stack: error message")
10035     # check that stop(1) was called
10036     (check-ints-equal *(edx+4) 2 "F - test-index-with-addr-base-on-stack: exit status")
10037     # don't restore from ebp
10038     81 0/subop/add %esp 8/imm32
10039     # . epilogue
10040     5d/pop-to-ebp
10041     c3/return
10042 
10043 test-index-with-wrong-index-type:
10044     # . prologue
10045     55/push-ebp
10046     89/<- %ebp 4/r32/esp
10047     # setup
10048     (clear-stream _test-input-stream)
10049     (clear-stream $_test-input-buffered-file->buffer)
10050     (clear-stream _test-output-stream)
10051     (clear-stream $_test-output-buffered-file->buffer)
10052     (clear-stream _test-error-stream)
10053     (clear-stream $_test-error-buffered-file->buffer)
10054     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10055     68/push 0/imm32
10056     68/push 0/imm32
10057     89/<- %edx 4/r32/esp
10058     (tailor-exit-descriptor %edx 0x10)
10059     #
10060     (write _test-input-stream "fn foo {\n")
10061     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
10062     (write _test-input-stream "  var b: boolean\n")
10063     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
10064     (write _test-input-stream "}\n")
10065     # convert
10066     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10067     # registers except esp clobbered at this point
10068     # restore ed
10069     89/<- %edx 4/r32/esp
10070     (flush _test-output-buffered-file)
10071     (flush _test-error-buffered-file)
10072 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10078     # check output
10079     (check-stream-equal _test-output-stream  ""  "F - test-index-with-wrong-index-type: output should be empty")
10080     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: second argument 'b' must be an int or offset"  "F - test-index-with-wrong-index-type: error message")
10081     # check that stop(1) was called
10082     (check-ints-equal *(edx+4) 2 "F - test-index-with-wrong-index-type: exit status")
10083     # don't restore from ebp
10084     81 0/subop/add %esp 8/imm32
10085     # . epilogue
10086     5d/pop-to-ebp
10087     c3/return
10088 
10089 test-index-with-offset-atom-index-type:
10090     # . prologue
10091     55/push-ebp
10092     89/<- %ebp 4/r32/esp
10093     # setup
10094     (clear-stream _test-input-stream)
10095     (clear-stream $_test-input-buffered-file->buffer)
10096     (clear-stream _test-output-stream)
10097     (clear-stream $_test-output-buffered-file->buffer)
10098     (clear-stream _test-error-stream)
10099     (clear-stream $_test-error-buffered-file->buffer)
10100     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10101     68/push 0/imm32
10102     68/push 0/imm32
10103     89/<- %edx 4/r32/esp
10104     (tailor-exit-descriptor %edx 0x10)
10105     #
10106     (write _test-input-stream "fn foo {\n")
10107     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
10108     (write _test-input-stream "  var b: offset\n")
10109     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
10110     (write _test-input-stream "}\n")
10111     # convert
10112     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10113     # registers except esp clobbered at this point
10114     # restore ed
10115     89/<- %edx 4/r32/esp
10116     (flush _test-output-buffered-file)
10117     (flush _test-error-buffered-file)
10118 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10124     # check output
10125     (check-stream-equal _test-output-stream  ""  "F - test-index-with-offset-atom-index-type: output should be empty")
10126     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: offset 'b' must specify the type of array elements"  "F - test-index-with-offset-atom-index-type: error message")
10127     # check that stop(1) was called
10128     (check-ints-equal *(edx+4) 2 "F - test-index-with-offset-atom-index-type: exit status")
10129     # don't restore from ebp
10130     81 0/subop/add %esp 8/imm32
10131     # . epilogue
10132     5d/pop-to-ebp
10133     c3/return
10134 
10135 test-index-with-offset-on-stack:
10136     # . prologue
10137     55/push-ebp
10138     89/<- %ebp 4/r32/esp
10139     # setup
10140     (clear-stream _test-input-stream)
10141     (clear-stream $_test-input-buffered-file->buffer)
10142     (clear-stream _test-output-stream)
10143     (clear-stream $_test-output-buffered-file->buffer)
10144     (clear-stream _test-error-stream)
10145     (clear-stream $_test-error-buffered-file->buffer)
10146     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10147     68/push 0/imm32
10148     68/push 0/imm32
10149     89/<- %edx 4/r32/esp
10150     (tailor-exit-descriptor %edx 0x10)
10151     #
10152     (write _test-input-stream "fn foo {\n")
10153     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
10154     (write _test-input-stream "  var b: int\n")
10155     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
10156     (write _test-input-stream "}\n")
10157     # convert
10158     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10159     # registers except esp clobbered at this point
10160     # restore ed
10161     89/<- %edx 4/r32/esp
10162     (flush _test-output-buffered-file)
10163     (flush _test-error-buffered-file)
10164 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10170     # check output
10171     (check-stream-equal _test-output-stream  ""  "F - test-index-with-offset-on-stack: output should be empty")
10172     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: second argument 'b' must be in a register"  "F - test-index-with-offset-on-stack: error message")
10173     # check that stop(1) was called
10174     (check-ints-equal *(edx+4) 2 "F - test-index-with-offset-on-stack: exit status")
10175     # don't restore from ebp
10176     81 0/subop/add %esp 8/imm32
10177     # . epilogue
10178     5d/pop-to-ebp
10179     c3/return
10180 
10181 test-index-needs-offset-type:
10182     # . prologue
10183     55/push-ebp
10184     89/<- %ebp 4/r32/esp
10185     # setup
10186     (clear-stream _test-input-stream)
10187     (clear-stream $_test-input-buffered-file->buffer)
10188     (clear-stream _test-output-stream)
10189     (clear-stream $_test-output-buffered-file->buffer)
10190     (clear-stream _test-error-stream)
10191     (clear-stream $_test-error-buffered-file->buffer)
10192     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10193     68/push 0/imm32
10194     68/push 0/imm32
10195     89/<- %edx 4/r32/esp
10196     (tailor-exit-descriptor %edx 0x10)
10197     #
10198     (write _test-input-stream "fn foo {\n")
10199     (write _test-input-stream "  var a/eax: (addr array t) <- copy 0\n")
10200     (write _test-input-stream "  var b/ebx: int <- copy 0\n")
10201     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
10202     (write _test-input-stream "}\n")
10203     (write _test-input-stream "type t {\n")  # size 12 is not a power of two
10204     (write _test-input-stream "  x: int\n")
10205     (write _test-input-stream "  y: int\n")
10206     (write _test-input-stream "  z: int\n")
10207     (write _test-input-stream "}\n")
10208     # convert
10209     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10210     # registers except esp clobbered at this point
10211     # restore ed
10212     89/<- %edx 4/r32/esp
10213     (flush _test-output-buffered-file)
10214     (flush _test-error-buffered-file)
10215 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10221     # check output
10222     (check-stream-equal _test-output-stream  ""  "F - test-index-needs-offset-type: output should be empty")
10223     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: cannot take an int for array 'a'; create an offset instead. See mu.md for details."  "F - test-index-needs-offset-type: error message")
10224     # check that stop(1) was called
10225     (check-ints-equal *(edx+4) 2 "F - test-index-needs-offset-type: exit status")
10226     # don't restore from ebp
10227     81 0/subop/add %esp 8/imm32
10228     # . epilogue
10229     5d/pop-to-ebp
10230     c3/return
10231 
10232 test-index-with-output-not-address:
10233     # . prologue
10234     55/push-ebp
10235     89/<- %ebp 4/r32/esp
10236     # setup
10237     (clear-stream _test-input-stream)
10238     (clear-stream $_test-input-buffered-file->buffer)
10239     (clear-stream _test-output-stream)
10240     (clear-stream $_test-output-buffered-file->buffer)
10241     (clear-stream _test-error-stream)
10242     (clear-stream $_test-error-buffered-file->buffer)
10243     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10244     68/push 0/imm32
10245     68/push 0/imm32
10246     89/<- %edx 4/r32/esp
10247     (tailor-exit-descriptor %edx 0x10)
10248     #
10249     (write _test-input-stream "fn foo {\n")
10250     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
10251     (write _test-input-stream "  var o/edi: int <- index a, 0\n")
10252     (write _test-input-stream "}\n")
10253     # convert
10254     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10255     # registers except esp clobbered at this point
10256     # restore ed
10257     89/<- %edx 4/r32/esp
10258     (flush _test-output-buffered-file)
10259     (flush _test-error-buffered-file)
10260 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10266     # check output
10267     (check-stream-equal _test-output-stream  ""  "F - test-index-with-output-not-address: output should be empty")
10268     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: output 'o' must be an addr"  "F - test-index-with-output-not-address: error message")
10269     # check that stop(1) was called
10270     (check-ints-equal *(edx+4) 2 "F - test-index-with-output-not-address: exit status")
10271     # don't restore from ebp
10272     81 0/subop/add %esp 8/imm32
10273     # . epilogue
10274     5d/pop-to-ebp
10275     c3/return
10276 
10277 test-index-with-output-not-address-2:
10278     # . prologue
10279     55/push-ebp
10280     89/<- %ebp 4/r32/esp
10281     # setup
10282     (clear-stream _test-input-stream)
10283     (clear-stream $_test-input-buffered-file->buffer)
10284     (clear-stream _test-output-stream)
10285     (clear-stream $_test-output-buffered-file->buffer)
10286     (clear-stream _test-error-stream)
10287     (clear-stream $_test-error-buffered-file->buffer)
10288     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10289     68/push 0/imm32
10290     68/push 0/imm32
10291     89/<- %edx 4/r32/esp
10292     (tailor-exit-descriptor %edx 0x10)
10293     #
10294     (write _test-input-stream "fn foo {\n")
10295     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
10296     (write _test-input-stream "  var o/edi: (int) <- index a, 0\n")
10297     (write _test-input-stream "}\n")
10298     # convert
10299     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10300     # registers except esp clobbered at this point
10301     # restore ed
10302     89/<- %edx 4/r32/esp
10303     (flush _test-output-buffered-file)
10304     (flush _test-error-buffered-file)
10305 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10311     # check output
10312     (check-stream-equal _test-output-stream  ""  "F - test-index-with-output-not-address-2: output should be empty")
10313     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: output 'o' must be an addr"  "F - test-index-with-output-not-address-2: error message")
10314     # check that stop(1) was called
10315     (check-ints-equal *(edx+4) 2 "F - test-index-with-output-not-address-2: exit status")
10316     # don't restore from ebp
10317     81 0/subop/add %esp 8/imm32
10318     # . epilogue
10319     5d/pop-to-ebp
10320     c3/return
10321 
10322 test-index-with-wrong-output-type:
10323     # . prologue
10324     55/push-ebp
10325     89/<- %ebp 4/r32/esp
10326     # setup
10327     (clear-stream _test-input-stream)
10328     (clear-stream $_test-input-buffered-file->buffer)
10329     (clear-stream _test-output-stream)
10330     (clear-stream $_test-output-buffered-file->buffer)
10331     (clear-stream _test-error-stream)
10332     (clear-stream $_test-error-buffered-file->buffer)
10333     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10334     68/push 0/imm32
10335     68/push 0/imm32
10336     89/<- %edx 4/r32/esp
10337     (tailor-exit-descriptor %edx 0x10)
10338     #
10339     (write _test-input-stream "fn foo {\n")
10340     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
10341     (write _test-input-stream "  var o/edi: (addr int) <- index a, 0\n")
10342     (write _test-input-stream "}\n")
10343     # convert
10344     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10345     # registers except esp clobbered at this point
10346     # restore ed
10347     89/<- %edx 4/r32/esp
10348     (flush _test-output-buffered-file)
10349     (flush _test-error-buffered-file)
10350 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10356     # check output
10357     (check-stream-equal _test-output-stream  ""  "F - test-index-with-wrong-output-type: output should be empty")
10358     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: output 'o' does not have the right type"  "F - test-index-with-wrong-output-type: error message")
10359     # check that stop(1) was called
10360     (check-ints-equal *(edx+4) 2 "F - test-index-with-wrong-output-type: exit status")
10361     # don't restore from ebp
10362     81 0/subop/add %esp 8/imm32
10363     # . epilogue
10364     5d/pop-to-ebp
10365     c3/return
10366 
10367 test-index-with-wrong-output-compound-type:
10368     # . prologue
10369     55/push-ebp
10370     89/<- %ebp 4/r32/esp
10371     # setup
10372     (clear-stream _test-input-stream)
10373     (clear-stream $_test-input-buffered-file->buffer)
10374     (clear-stream _test-output-stream)
10375     (clear-stream $_test-output-buffered-file->buffer)
10376     (clear-stream _test-error-stream)
10377     (clear-stream $_test-error-buffered-file->buffer)
10378     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10379     68/push 0/imm32
10380     68/push 0/imm32
10381     89/<- %edx 4/r32/esp
10382     (tailor-exit-descriptor %edx 0x10)
10383     #
10384     (write _test-input-stream "fn foo {\n")
10385     (write _test-input-stream "  var a/ebx: (addr array handle boolean) <- copy 0\n")
10386     (write _test-input-stream "  var o/edi: (addr handle int) <- index a, 0\n")
10387     (write _test-input-stream "}\n")
10388     # convert
10389     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10390     # registers except esp clobbered at this point
10391     # restore ed
10392     89/<- %edx 4/r32/esp
10393     (flush _test-output-buffered-file)
10394     (flush _test-error-buffered-file)
10395 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10401     # check output
10402     (check-stream-equal _test-output-stream  ""  "F - test-index-with-wrong-output-compound-type: output should be empty")
10403     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: output 'o' does not have the right type"  "F - test-index-with-wrong-output-compound-type: error message")
10404     # check that stop(1) was called
10405     (check-ints-equal *(edx+4) 2 "F - test-index-with-wrong-output-compound-type: exit status")
10406     # don't restore from ebp
10407     81 0/subop/add %esp 8/imm32
10408     # . epilogue
10409     5d/pop-to-ebp
10410     c3/return
10411 
10412 test-index-with-no-inouts:
10413     # . prologue
10414     55/push-ebp
10415     89/<- %ebp 4/r32/esp
10416     # setup
10417     (clear-stream _test-input-stream)
10418     (clear-stream $_test-input-buffered-file->buffer)
10419     (clear-stream _test-output-stream)
10420     (clear-stream $_test-output-buffered-file->buffer)
10421     (clear-stream _test-error-stream)
10422     (clear-stream $_test-error-buffered-file->buffer)
10423     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10424     68/push 0/imm32
10425     68/push 0/imm32
10426     89/<- %edx 4/r32/esp
10427     (tailor-exit-descriptor %edx 0x10)
10428     #
10429     (write _test-input-stream "fn foo {\n")
10430     (write _test-input-stream "  var c/ecx: (addr int) <- index\n")
10431     (write _test-input-stream "}\n")
10432     # convert
10433     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10434     # registers except esp clobbered at this point
10435     # restore ed
10436     89/<- %edx 4/r32/esp
10437     (flush _test-output-buffered-file)
10438     (flush _test-error-buffered-file)
10439 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10445     # check output
10446     (check-stream-equal _test-output-stream  ""  "F - test-index-with-no-inouts: output should be empty")
10447     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: too few inouts (2 required)"  "F - test-index-with-no-inouts: error message")
10448     # check that stop(1) was called
10449     (check-ints-equal *(edx+4) 2 "F - test-index-with-no-inouts: exit status")
10450     # don't restore from ebp
10451     81 0/subop/add %esp 8/imm32
10452     # . epilogue
10453     5d/pop-to-ebp
10454     c3/return
10455 
10456 test-index-with-too-few-inouts:
10457     # . prologue
10458     55/push-ebp
10459     89/<- %ebp 4/r32/esp
10460     # setup
10461     (clear-stream _test-input-stream)
10462     (clear-stream $_test-input-buffered-file->buffer)
10463     (clear-stream _test-output-stream)
10464     (clear-stream $_test-output-buffered-file->buffer)
10465     (clear-stream _test-error-stream)
10466     (clear-stream $_test-error-buffered-file->buffer)
10467     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10468     68/push 0/imm32
10469     68/push 0/imm32
10470     89/<- %edx 4/r32/esp
10471     (tailor-exit-descriptor %edx 0x10)
10472     #
10473     (write _test-input-stream "fn foo {\n")
10474     (write _test-input-stream "  var a: (array int 3)\n")
10475     (write _test-input-stream "  var c/ecx: (addr int) <- index a\n")
10476     (write _test-input-stream "}\n")
10477     # convert
10478     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10479     # registers except esp clobbered at this point
10480     # restore ed
10481     89/<- %edx 4/r32/esp
10482     (flush _test-output-buffered-file)
10483     (flush _test-error-buffered-file)
10484 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10490     # check output
10491     (check-stream-equal _test-output-stream  ""  "F - test-index-with-too-few-inouts: output should be empty")
10492     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: too few inouts (2 required)"  "F - test-index-with-too-few-inouts: error message")
10493     # check that stop(1) was called
10494     (check-ints-equal *(edx+4) 2 "F - test-index-with-too-few-inouts: exit status")
10495     # don't restore from ebp
10496     81 0/subop/add %esp 8/imm32
10497     # . epilogue
10498     5d/pop-to-ebp
10499     c3/return
10500 
10501 test-index-with-too-many-inouts:
10502     # . prologue
10503     55/push-ebp
10504     89/<- %ebp 4/r32/esp
10505     # setup
10506     (clear-stream _test-input-stream)
10507     (clear-stream $_test-input-buffered-file->buffer)
10508     (clear-stream _test-output-stream)
10509     (clear-stream $_test-output-buffered-file->buffer)
10510     (clear-stream _test-error-stream)
10511     (clear-stream $_test-error-buffered-file->buffer)
10512     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10513     68/push 0/imm32
10514     68/push 0/imm32
10515     89/<- %edx 4/r32/esp
10516     (tailor-exit-descriptor %edx 0x10)
10517     #
10518     (write _test-input-stream "fn foo {\n")
10519     (write _test-input-stream "  var a: (array int 3)\n")
10520     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0, 0\n")
10521     (write _test-input-stream "}\n")
10522     # convert
10523     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10524     # registers except esp clobbered at this point
10525     # restore ed
10526     89/<- %edx 4/r32/esp
10527     (flush _test-output-buffered-file)
10528     (flush _test-error-buffered-file)
10529 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10535     # check output
10536     (check-stream-equal _test-output-stream  ""  "F - test-index-with-too-many-inouts: output should be empty")
10537     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: too many inouts (2 required)"  "F - test-index-with-too-many-inouts: error message")
10538     # check that stop(1) was called
10539     (check-ints-equal *(edx+4) 2 "F - test-index-with-too-many-inouts: exit status")
10540     # don't restore from ebp
10541     81 0/subop/add %esp 8/imm32
10542     # . epilogue
10543     5d/pop-to-ebp
10544     c3/return
10545 
10546 test-index-with-no-output:
10547     # . prologue
10548     55/push-ebp
10549     89/<- %ebp 4/r32/esp
10550     # setup
10551     (clear-stream _test-input-stream)
10552     (clear-stream $_test-input-buffered-file->buffer)
10553     (clear-stream _test-output-stream)
10554     (clear-stream $_test-output-buffered-file->buffer)
10555     (clear-stream _test-error-stream)
10556     (clear-stream $_test-error-buffered-file->buffer)
10557     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10558     68/push 0/imm32
10559     68/push 0/imm32
10560     89/<- %edx 4/r32/esp
10561     (tailor-exit-descriptor %edx 0x10)
10562     #
10563     (write _test-input-stream "fn foo {\n")
10564     (write _test-input-stream "  var a: (array int 3)\n")
10565     (write _test-input-stream "  index a, 0\n")
10566     (write _test-input-stream "}\n")
10567     # convert
10568     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10569     # registers except esp clobbered at this point
10570     # restore ed
10571     89/<- %edx 4/r32/esp
10572     (flush _test-output-buffered-file)
10573     (flush _test-error-buffered-file)
10574 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10580     # check output
10581     (check-stream-equal _test-output-stream  ""  "F - test-index-with-no-output: output should be empty")
10582     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: must have an output"  "F - test-index-with-no-output: error message")
10583     # check that stop(1) was called
10584     (check-ints-equal *(edx+4) 2 "F - test-index-with-no-output: exit status")
10585     # don't restore from ebp
10586     81 0/subop/add %esp 8/imm32
10587     # . epilogue
10588     5d/pop-to-ebp
10589     c3/return
10590 
10591 test-index-with-too-many-outputs:
10592     # . prologue
10593     55/push-ebp
10594     89/<- %ebp 4/r32/esp
10595     # setup
10596     (clear-stream _test-input-stream)
10597     (clear-stream $_test-input-buffered-file->buffer)
10598     (clear-stream _test-output-stream)
10599     (clear-stream $_test-output-buffered-file->buffer)
10600     (clear-stream _test-error-stream)
10601     (clear-stream $_test-error-buffered-file->buffer)
10602     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10603     68/push 0/imm32
10604     68/push 0/imm32
10605     89/<- %edx 4/r32/esp
10606     (tailor-exit-descriptor %edx 0x10)
10607     #
10608     (write _test-input-stream "fn foo {\n")
10609     (write _test-input-stream "  var a: (array int 3)\n")
10610     (write _test-input-stream "  var b/eax: (addr int) <- copy 0\n")
10611     (write _test-input-stream "  var c/ecx: (addr int) <- copy 0\n")
10612     (write _test-input-stream "  b, c <- index a, 0\n")
10613     (write _test-input-stream "}\n")
10614     # convert
10615     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10616     # registers except esp clobbered at this point
10617     # restore ed
10618     89/<- %edx 4/r32/esp
10619     (flush _test-output-buffered-file)
10620     (flush _test-error-buffered-file)
10621 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10627     # check output
10628     (check-stream-equal _test-output-stream  ""  "F - test-index-with-too-many-outputs: output should be empty")
10629     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: too many outputs (1 required)"  "F - test-index-with-too-many-outputs: error message")
10630     # check that stop(1) was called
10631     (check-ints-equal *(edx+4) 2 "F - test-index-with-too-many-outputs: exit status")
10632     # don't restore from ebp
10633     81 0/subop/add %esp 8/imm32
10634     # . epilogue
10635     5d/pop-to-ebp
10636     c3/return
10637 
10638 test-compute-offset-with-non-array-atom-base-type:
10639     # . prologue
10640     55/push-ebp
10641     89/<- %ebp 4/r32/esp
10642     # setup
10643     (clear-stream _test-input-stream)
10644     (clear-stream $_test-input-buffered-file->buffer)
10645     (clear-stream _test-output-stream)
10646     (clear-stream $_test-output-buffered-file->buffer)
10647     (clear-stream _test-error-stream)
10648     (clear-stream $_test-error-buffered-file->buffer)
10649     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10650     68/push 0/imm32
10651     68/push 0/imm32
10652     89/<- %edx 4/r32/esp
10653     (tailor-exit-descriptor %edx 0x10)
10654     #
10655     (write _test-input-stream "fn foo {\n")
10656     (write _test-input-stream "  var a: int\n")
10657     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0\n")
10658     (write _test-input-stream "}\n")
10659     # convert
10660     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10661     # registers except esp clobbered at this point
10662     # restore ed
10663     89/<- %edx 4/r32/esp
10664     (flush _test-output-buffered-file)
10665     (flush _test-error-buffered-file)
10666 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10672     # check output
10673     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-non-array-atom-base-type: output should be empty")
10674     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: var 'a' is not an array"  "F - test-compute-offset-with-non-array-atom-base-type: error message")
10675     # check that stop(1) was called
10676     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-non-array-atom-base-type: exit status")
10677     # don't restore from ebp
10678     81 0/subop/add %esp 8/imm32
10679     # . epilogue
10680     5d/pop-to-ebp
10681     c3/return
10682 
10683 test-compute-offset-with-non-array-compound-base-type:
10684     # . prologue
10685     55/push-ebp
10686     89/<- %ebp 4/r32/esp
10687     # setup
10688     (clear-stream _test-input-stream)
10689     (clear-stream $_test-input-buffered-file->buffer)
10690     (clear-stream _test-output-stream)
10691     (clear-stream $_test-output-buffered-file->buffer)
10692     (clear-stream _test-error-stream)
10693     (clear-stream $_test-error-buffered-file->buffer)
10694     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10695     68/push 0/imm32
10696     68/push 0/imm32
10697     89/<- %edx 4/r32/esp
10698     (tailor-exit-descriptor %edx 0x10)
10699     #
10700     (write _test-input-stream "fn foo {\n")
10701     (write _test-input-stream "  var a: (handle int)\n")
10702     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0\n")
10703     (write _test-input-stream "}\n")
10704     # convert
10705     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10706     # registers except esp clobbered at this point
10707     # restore ed
10708     89/<- %edx 4/r32/esp
10709     (flush _test-output-buffered-file)
10710     (flush _test-error-buffered-file)
10711 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10717     # check output
10718     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-non-array-compound-base-type: output should be empty")
10719     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: var 'a' is not an array"  "F - test-compute-offset-with-non-array-compound-base-type: error message")
10720     # check that stop(1) was called
10721     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-non-array-compound-base-type: exit status")
10722     # don't restore from ebp
10723     81 0/subop/add %esp 8/imm32
10724     # . epilogue
10725     5d/pop-to-ebp
10726     c3/return
10727 
10728 test-compute-offset-with-non-array-compound-base-type-2:
10729     # . prologue
10730     55/push-ebp
10731     89/<- %ebp 4/r32/esp
10732     # setup
10733     (clear-stream _test-input-stream)
10734     (clear-stream $_test-input-buffered-file->buffer)
10735     (clear-stream _test-output-stream)
10736     (clear-stream $_test-output-buffered-file->buffer)
10737     (clear-stream _test-error-stream)
10738     (clear-stream $_test-error-buffered-file->buffer)
10739     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10740     68/push 0/imm32
10741     68/push 0/imm32
10742     89/<- %edx 4/r32/esp
10743     (tailor-exit-descriptor %edx 0x10)
10744     #
10745     (write _test-input-stream "fn foo {\n")
10746     (write _test-input-stream "  var a: (addr int)\n")
10747     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0\n")
10748     (write _test-input-stream "}\n")
10749     # convert
10750     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10751     # registers except esp clobbered at this point
10752     # restore ed
10753     89/<- %edx 4/r32/esp
10754     (flush _test-output-buffered-file)
10755     (flush _test-error-buffered-file)
10756 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10762     # check output
10763     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-non-array-compound-base-type-2: output should be empty")
10764     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: var 'a' is not an array"  "F - test-compute-offset-with-non-array-compound-base-type-2: error message")
10765     # check that stop(1) was called
10766     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-non-array-compound-base-type-2: exit status")
10767     # don't restore from ebp
10768     81 0/subop/add %esp 8/imm32
10769     # . epilogue
10770     5d/pop-to-ebp
10771     c3/return
10772 
10773 test-compute-offset-with-array-atom-base-type:
10774     # . prologue
10775     55/push-ebp
10776     89/<- %ebp 4/r32/esp
10777     # setup
10778     (clear-stream _test-input-stream)
10779     (clear-stream $_test-input-buffered-file->buffer)
10780     (clear-stream _test-output-stream)
10781     (clear-stream $_test-output-buffered-file->buffer)
10782     (clear-stream _test-error-stream)
10783     (clear-stream $_test-error-buffered-file->buffer)
10784     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10785     68/push 0/imm32
10786     68/push 0/imm32
10787     89/<- %edx 4/r32/esp
10788     (tailor-exit-descriptor %edx 0x10)
10789     #
10790     (write _test-input-stream "fn foo {\n")
10791     (write _test-input-stream "  var a: array\n")
10792     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0\n")
10793     (write _test-input-stream "}\n")
10794     # convert
10795     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10796     # registers except esp clobbered at this point
10797     # restore ed
10798     89/<- %edx 4/r32/esp
10799     (flush _test-output-buffered-file)
10800     (flush _test-error-buffered-file)
10801 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10807     # check output
10808     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-array-atom-base-type: output should be empty")
10809     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: array 'a' must specify the type of its elements"  "F - test-compute-offset-with-array-atom-base-type: error message")
10810     # check that stop(1) was called
10811     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-array-atom-base-type: exit status")
10812     # don't restore from ebp
10813     81 0/subop/add %esp 8/imm32
10814     # . epilogue
10815     5d/pop-to-ebp
10816     c3/return
10817 
10818 test-compute-offset-with-wrong-index-type:
10819     # . prologue
10820     55/push-ebp
10821     89/<- %ebp 4/r32/esp
10822     # setup
10823     (clear-stream _test-input-stream)
10824     (clear-stream $_test-input-buffered-file->buffer)
10825     (clear-stream _test-output-stream)
10826     (clear-stream $_test-output-buffered-file->buffer)
10827     (clear-stream _test-error-stream)
10828     (clear-stream $_test-error-buffered-file->buffer)
10829     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10830     68/push 0/imm32
10831     68/push 0/imm32
10832     89/<- %edx 4/r32/esp
10833     (tailor-exit-descriptor %edx 0x10)
10834     #
10835     (write _test-input-stream "fn foo {\n")
10836     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
10837     (write _test-input-stream "  var b: boolean\n")
10838     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, b\n")
10839     (write _test-input-stream "}\n")
10840     # convert
10841     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10842     # registers except esp clobbered at this point
10843     # restore ed
10844     89/<- %edx 4/r32/esp
10845     (flush _test-output-buffered-file)
10846     (flush _test-error-buffered-file)
10847 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10853     # check output
10854     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-wrong-index-type: output should be empty")
10855     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: second argument 'b' must be an int"  "F - test-compute-offset-with-wrong-index-type: error message")
10856     # check that stop(1) was called
10857     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-wrong-index-type: exit status")
10858     # don't restore from ebp
10859     81 0/subop/add %esp 8/imm32
10860     # . epilogue
10861     5d/pop-to-ebp
10862     c3/return
10863 
10864 test-compute-offset-with-output-not-offset:
10865     # . prologue
10866     55/push-ebp
10867     89/<- %ebp 4/r32/esp
10868     # setup
10869     (clear-stream _test-input-stream)
10870     (clear-stream $_test-input-buffered-file->buffer)
10871     (clear-stream _test-output-stream)
10872     (clear-stream $_test-output-buffered-file->buffer)
10873     (clear-stream _test-error-stream)
10874     (clear-stream $_test-error-buffered-file->buffer)
10875     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10876     68/push 0/imm32
10877     68/push 0/imm32
10878     89/<- %edx 4/r32/esp
10879     (tailor-exit-descriptor %edx 0x10)
10880     #
10881     (write _test-input-stream "fn foo {\n")
10882     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
10883     (write _test-input-stream "  var o/edi: int <- compute-offset a, 0\n")
10884     (write _test-input-stream "}\n")
10885     # convert
10886     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10887     # registers except esp clobbered at this point
10888     # restore ed
10889     89/<- %edx 4/r32/esp
10890     (flush _test-output-buffered-file)
10891     (flush _test-error-buffered-file)
10892 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10898     # check output
10899     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-output-not-offset: output should be empty")
10900     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: output 'o' must be an offset"  "F - test-compute-offset-with-output-not-offset: error message")
10901     # check that stop(1) was called
10902     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-output-not-offset: exit status")
10903     # don't restore from ebp
10904     81 0/subop/add %esp 8/imm32
10905     # . epilogue
10906     5d/pop-to-ebp
10907     c3/return
10908 
10909 test-compute-offset-with-output-not-address-2:
10910     # . prologue
10911     55/push-ebp
10912     89/<- %ebp 4/r32/esp
10913     # setup
10914     (clear-stream _test-input-stream)
10915     (clear-stream $_test-input-buffered-file->buffer)
10916     (clear-stream _test-output-stream)
10917     (clear-stream $_test-output-buffered-file->buffer)
10918     (clear-stream _test-error-stream)
10919     (clear-stream $_test-error-buffered-file->buffer)
10920     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10921     68/push 0/imm32
10922     68/push 0/imm32
10923     89/<- %edx 4/r32/esp
10924     (tailor-exit-descriptor %edx 0x10)
10925     #
10926     (write _test-input-stream "fn foo {\n")
10927     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
10928     (write _test-input-stream "  var o/edi: (int) <- compute-offset a, 0\n")
10929     (write _test-input-stream "}\n")
10930     # convert
10931     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10932     # registers except esp clobbered at this point
10933     # restore ed
10934     89/<- %edx 4/r32/esp
10935     (flush _test-output-buffered-file)
10936     (flush _test-error-buffered-file)
10937 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10943     # check output
10944     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-output-not-address-2: output should be empty")
10945     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: output 'o' must be an offset"  "F - test-compute-offset-with-output-not-address-2: error message")
10946     # check that stop(1) was called
10947     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-output-not-address-2: exit status")
10948     # don't restore from ebp
10949     81 0/subop/add %esp 8/imm32
10950     # . epilogue
10951     5d/pop-to-ebp
10952     c3/return
10953 
10954 test-compute-offset-with-wrong-output-type:
10955     # . prologue
10956     55/push-ebp
10957     89/<- %ebp 4/r32/esp
10958     # setup
10959     (clear-stream _test-input-stream)
10960     (clear-stream $_test-input-buffered-file->buffer)
10961     (clear-stream _test-output-stream)
10962     (clear-stream $_test-output-buffered-file->buffer)
10963     (clear-stream _test-error-stream)
10964     (clear-stream $_test-error-buffered-file->buffer)
10965     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
10966     68/push 0/imm32
10967     68/push 0/imm32
10968     89/<- %edx 4/r32/esp
10969     (tailor-exit-descriptor %edx 0x10)
10970     #
10971     (write _test-input-stream "fn foo {\n")
10972     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
10973     (write _test-input-stream "  var o/edi: (offset int) <- compute-offset a, 0\n")
10974     (write _test-input-stream "}\n")
10975     # convert
10976     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
10977     # registers except esp clobbered at this point
10978     # restore ed
10979     89/<- %edx 4/r32/esp
10980     (flush _test-output-buffered-file)
10981     (flush _test-error-buffered-file)
10982 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10988     # check output
10989     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-wrong-output-type: output should be empty")
10990     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: output 'o' does not have the right type"  "F - test-compute-offset-with-wrong-output-type: error message")
10991     # check that stop(1) was called
10992     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-wrong-output-type: exit status")
10993     # don't restore from ebp
10994     81 0/subop/add %esp 8/imm32
10995     # . epilogue
10996     5d/pop-to-ebp
10997     c3/return
10998 
10999 test-compute-offset-with-wrong-output-compound-type:
11000     # . prologue
11001     55/push-ebp
11002     89/<- %ebp 4/r32/esp
11003     # setup
11004     (clear-stream _test-input-stream)
11005     (clear-stream $_test-input-buffered-file->buffer)
11006     (clear-stream _test-output-stream)
11007     (clear-stream $_test-output-buffered-file->buffer)
11008     (clear-stream _test-error-stream)
11009     (clear-stream $_test-error-buffered-file->buffer)
11010     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11011     68/push 0/imm32
11012     68/push 0/imm32
11013     89/<- %edx 4/r32/esp
11014     (tailor-exit-descriptor %edx 0x10)
11015     #
11016     (write _test-input-stream "fn foo {\n")
11017     (write _test-input-stream "  var a/ebx: (addr array handle boolean) <- copy 0\n")
11018     (write _test-input-stream "  var o/edi: (offset handle int) <- compute-offset a, 0\n")
11019     (write _test-input-stream "}\n")
11020     # convert
11021     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11022     # registers except esp clobbered at this point
11023     # restore ed
11024     89/<- %edx 4/r32/esp
11025     (flush _test-output-buffered-file)
11026     (flush _test-error-buffered-file)
11027 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
11033     # check output
11034     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-wrong-output-compound-type: output should be empty")
11035     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: output 'o' does not have the right type"  "F - test-compute-offset-with-wrong-output-compound-type: error message")
11036     # check that stop(1) was called
11037     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-wrong-output-compound-type: exit status")
11038     # don't restore from ebp
11039     81 0/subop/add %esp 8/imm32
11040     # . epilogue
11041     5d/pop-to-ebp
11042     c3/return
11043 
11044 test-compute-offset-with-no-inouts:
11045     # . prologue
11046     55/push-ebp
11047     89/<- %ebp 4/r32/esp
11048     # setup
11049     (clear-stream _test-input-stream)
11050     (clear-stream $_test-input-buffered-file->buffer)
11051     (clear-stream _test-output-stream)
11052     (clear-stream $_test-output-buffered-file->buffer)
11053     (clear-stream _test-error-stream)
11054     (clear-stream $_test-error-buffered-file->buffer)
11055     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11056     68/push 0/imm32
11057     68/push 0/imm32
11058     89/<- %edx 4/r32/esp
11059     (tailor-exit-descriptor %edx 0x10)
11060     #
11061     (write _test-input-stream "fn foo {\n")
11062     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset\n")
11063     (write _test-input-stream "}\n")
11064     # convert
11065     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11066     # registers except esp clobbered at this point
11067     # restore ed
11068     89/<- %edx 4/r32/esp
11069     (flush _test-output-buffered-file)
11070     (flush _test-error-buffered-file)
11071 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
11077     # check output
11078     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-no-inouts: output should be empty")
11079     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: too few inouts (2 required)"  "F - test-compute-offset-with-no-inouts: error message")
11080     # check that stop(1) was called
11081     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-no-inouts: exit status")
11082     # don't restore from ebp
11083     81 0/subop/add %esp 8/imm32
11084     # . epilogue
11085     5d/pop-to-ebp
11086     c3/return
11087 
11088 test-compute-offset-with-too-few-inouts:
11089     # . prologue
11090     55/push-ebp
11091     89/<- %ebp 4/r32/esp
11092     # setup
11093     (clear-stream _test-input-stream)
11094     (clear-stream $_test-input-buffered-file->buffer)
11095     (clear-stream _test-output-stream)
11096     (clear-stream $_test-output-buffered-file->buffer)
11097     (clear-stream _test-error-stream)
11098     (clear-stream $_test-error-buffered-file->buffer)
11099     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11100     68/push 0/imm32
11101     68/push 0/imm32
11102     89/<- %edx 4/r32/esp
11103     (tailor-exit-descriptor %edx 0x10)
11104     #
11105     (write _test-input-stream "fn foo {\n")
11106     (write _test-input-stream "  var a: (array int 3)\n")
11107     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a\n")
11108     (write _test-input-stream "}\n")
11109     # convert
11110     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11111     # registers except esp clobbered at this point
11112     # restore ed
11113     89/<- %edx 4/r32/esp
11114     (flush _test-output-buffered-file)
11115     (flush _test-error-buffered-file)
11116 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
11122     # check output
11123     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-too-few-inouts: output should be empty")
11124     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: too few inouts (2 required)"  "F - test-compute-offset-with-too-few-inouts: error message")
11125     # check that stop(1) was called
11126     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-too-few-inouts: exit status")
11127     # don't restore from ebp
11128     81 0/subop/add %esp 8/imm32
11129     # . epilogue
11130     5d/pop-to-ebp
11131     c3/return
11132 
11133 test-compute-offset-with-too-many-inouts:
11134     # . prologue
11135     55/push-ebp
11136     89/<- %ebp 4/r32/esp
11137     # setup
11138     (clear-stream _test-input-stream)
11139     (clear-stream $_test-input-buffered-file->buffer)
11140     (clear-stream _test-output-stream)
11141     (clear-stream $_test-output-buffered-file->buffer)
11142     (clear-stream _test-error-stream)
11143     (clear-stream $_test-error-buffered-file->buffer)
11144     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11145     68/push 0/imm32
11146     68/push 0/imm32
11147     89/<- %edx 4/r32/esp
11148     (tailor-exit-descriptor %edx 0x10)
11149     #
11150     (write _test-input-stream "fn foo {\n")
11151     (write _test-input-stream "  var a: (array int 3)\n")
11152     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0, 0\n")
11153     (write _test-input-stream "}\n")
11154     # convert
11155     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11156     # registers except esp clobbered at this point
11157     # restore ed
11158     89/<- %edx 4/r32/esp
11159     (flush _test-output-buffered-file)
11160     (flush _test-error-buffered-file)
11161 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
11167     # check output
11168     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-too-many-inouts: output should be empty")
11169     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: too many inouts (2 required)"  "F - test-compute-offset-with-too-many-inouts: error message")
11170     # check that stop(1) was called
11171     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-too-many-inouts: exit status")
11172     # don't restore from ebp
11173     81 0/subop/add %esp 8/imm32
11174     # . epilogue
11175     5d/pop-to-ebp
11176     c3/return
11177 
11178 test-compute-offset-with-no-output:
11179     # . prologue
11180     55/push-ebp
11181     89/<- %ebp 4/r32/esp
11182     # setup
11183     (clear-stream _test-input-stream)
11184     (clear-stream $_test-input-buffered-file->buffer)
11185     (clear-stream _test-output-stream)
11186     (clear-stream $_test-output-buffered-file->buffer)
11187     (clear-stream _test-error-stream)
11188     (clear-stream $_test-error-buffered-file->buffer)
11189     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11190     68/push 0/imm32
11191     68/push 0/imm32
11192     89/<- %edx 4/r32/esp
11193     (tailor-exit-descriptor %edx 0x10)
11194     #
11195     (write _test-input-stream "fn foo {\n")
11196     (write _test-input-stream "  var a: (array int 3)\n")
11197     (write _test-input-stream "  compute-offset a, 0\n")
11198     (write _test-input-stream "}\n")
11199     # convert
11200     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11201     # registers except esp clobbered at this point
11202     # restore ed
11203     89/<- %edx 4/r32/esp
11204     (flush _test-output-buffered-file)
11205     (flush _test-error-buffered-file)
11206 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
11212     # check output
11213     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-no-output: output should be empty")
11214     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: must have an output"  "F - test-compute-offset-with-no-output: error message")
11215     # check that stop(1) was called
11216     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-no-output: exit status")
11217     # don't restore from ebp
11218     81 0/subop/add %esp 8/imm32
11219     # . epilogue
11220     5d/pop-to-ebp
11221     c3/return
11222 
11223 test-compute-offset-with-too-many-outputs:
11224     # . prologue
11225     55/push-ebp
11226     89/<- %ebp 4/r32/esp
11227     # setup
11228     (clear-stream _test-input-stream)
11229     (clear-stream $_test-input-buffered-file->buffer)
11230     (clear-stream _test-output-stream)
11231     (clear-stream $_test-output-buffered-file->buffer)
11232     (clear-stream _test-error-stream)
11233     (clear-stream $_test-error-buffered-file->buffer)
11234     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11235     68/push 0/imm32
11236     68/push 0/imm32
11237     89/<- %edx 4/r32/esp
11238     (tailor-exit-descriptor %edx 0x10)
11239     #
11240     (write _test-input-stream "fn foo {\n")
11241     (write _test-input-stream "  var a: (array int 3)\n")
11242     (write _test-input-stream "  var b/eax: (offset int) <- compute-offset a, 0\n")
11243     (write _test-input-stream "  var c/ecx: (addr int) <- copy 0\n")
11244     (write _test-input-stream "  b, c <- compute-offset a, 0\n")
11245     (write _test-input-stream "}\n")
11246     # convert
11247     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11248     # registers except esp clobbered at this point
11249     # restore ed
11250     89/<- %edx 4/r32/esp
11251     (flush _test-output-buffered-file)
11252     (flush _test-error-buffered-file)
11253 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
11259     # check output
11260     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-too-many-outputs: output should be empty")
11261     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: too many outputs (1 required)"  "F - test-compute-offset-with-too-many-outputs: error message")
11262     # check that stop(1) was called
11263     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-too-many-outputs: exit status")
11264     # don't restore from ebp
11265     81 0/subop/add %esp 8/imm32
11266     # . epilogue
11267     5d/pop-to-ebp
11268     c3/return
11269 
11270 test-convert-read-from-stream:
11271     # . prologue
11272     55/push-ebp
11273     89/<- %ebp 4/r32/esp
11274     # setup
11275     (clear-stream _test-input-stream)
11276     (clear-stream $_test-input-buffered-file->buffer)
11277     (clear-stream _test-output-stream)
11278     (clear-stream $_test-output-buffered-file->buffer)
11279     #
11280     (write _test-input-stream "fn foo {\n")
11281     (write _test-input-stream "  var s/esi: (addr stream int) <- copy 0\n")
11282     (write _test-input-stream "  var o/ecx: (addr int) <- copy 0\n")
11283     (write _test-input-stream "  read-from-stream s, o\n")
11284     (write _test-input-stream "}\n")
11285     # convert
11286     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
11287     # registers except esp clobbered at this point
11288     # restore ed
11289     89/<- %edx 4/r32/esp
11290     (flush _test-output-buffered-file)
11291     (flush _test-error-buffered-file)
11292 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
11298     # check output
11299     (check-next-stream-line-equal _test-output-stream "foo:"                            "F - test-convert-read-from-stream/0")
11300     (check-next-stream-line-equal _test-output-stream "  # . prologue"                  "F - test-convert-read-from-stream/1")
11301     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                   "F - test-convert-read-from-stream/2")
11302     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"          "F - test-convert-read-from-stream/3")
11303     (check-next-stream-line-equal _test-output-stream "  {"                             "F - test-convert-read-from-stream/4")
11304     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"           "F - test-convert-read-from-stream/5")
11305     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %esi"        "F - test-convert-read-from-stream/6")
11306     (check-next-stream-line-equal _test-output-stream "    be/copy-to-esi 0/imm32"      "F - test-convert-read-from-stream/7")
11307     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"        "F - test-convert-read-from-stream/8")
11308     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"      "F - test-convert-read-from-stream/9")
11309     (check-next-stream-line-equal _test-output-stream "    (read-from-stream %esi %ecx 0x00000004)"  "F - test-convert-read-from-stream/10")
11310     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-read-from-stream/11")
11311     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %esi"         "F - test-convert-read-from-stream/12")
11312     (check-next-stream-line-equal _test-output-stream "  }"                             "F - test-convert-read-from-stream/13")
11313     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"          "F - test-convert-read-from-stream/14")
11314     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                  "F - test-convert-read-from-stream/15")
11315     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"          "F - test-convert-read-from-stream/16")
11316     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                 "F - test-convert-read-from-stream/17")
11317     (check-next-stream-line-equal _test-output-stream "  c3/return"                     "F - test-convert-read-from-stream/18")
11318     # . epilogue
11319     89/<- %esp 5/r32/ebp
11320     5d/pop-to-ebp
11321     c3/return
11322 
11323 test-convert-read-from-stream-with-correct-payload-size:
11324     # . prologue
11325     55/push-ebp
11326     89/<- %ebp 4/r32/esp
11327     # setup
11328     (clear-stream _test-input-stream)
11329     (clear-stream $_test-input-buffered-file->buffer)
11330     (clear-stream _test-output-stream)
11331     (clear-stream $_test-output-buffered-file->buffer)
11332     #
11333     (write _test-input-stream "fn foo {\n")
11334     (write _test-input-stream "  var s/esi: (addr stream handle int) <- copy 0\n")
11335     (write _test-input-stream "  var o/ecx: (addr handle int) <- copy 0\n")
11336     (write _test-input-stream "  read-from-stream s, o\n")
11337     (write _test-input-stream "}\n")
11338     # convert
11339     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
11340     # registers except esp clobbered at this point
11341     # restore ed
11342     89/<- %edx 4/r32/esp
11343     (flush _test-output-buffered-file)
11344     (flush _test-error-buffered-file)
11345 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
11351     # check output
11352     (check-next-stream-line-equal _test-output-stream "foo:"                            "F - test-convert-read-from-stream-with-correct-payload-size/0")
11353     (check-next-stream-line-equal _test-output-stream "  # . prologue"                  "F - test-convert-read-from-stream-with-correct-payload-size/1")
11354     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                   "F - test-convert-read-from-stream-with-correct-payload-size/2")
11355     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"          "F - test-convert-read-from-stream-with-correct-payload-size/3")
11356     (check-next-stream-line-equal _test-output-stream "  {"                             "F - test-convert-read-from-stream-with-correct-payload-size/4")
11357     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"           "F - test-convert-read-from-stream-with-correct-payload-size/5")
11358     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %esi"        "F - test-convert-read-from-stream-with-correct-payload-size/6")
11359     (check-next-stream-line-equal _test-output-stream "    be/copy-to-esi 0/imm32"      "F - test-convert-read-from-stream-with-correct-payload-size/7")
11360     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"        "F - test-convert-read-from-stream-with-correct-payload-size/8")
11361     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"      "F - test-convert-read-from-stream-with-correct-payload-size/9")
11362     (check-next-stream-line-equal _test-output-stream "    (read-from-stream %esi %ecx 0x00000008)"  "F - test-convert-read-from-stream-with-correct-payload-size/10")
11363     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-read-from-stream-with-correct-payload-size/11")
11364     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %esi"         "F - test-convert-read-from-stream-with-correct-payload-size/12")
11365     (check-next-stream-line-equal _test-output-stream "  }"                             "F - test-convert-read-from-stream-with-correct-payload-size/13")
11366     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"          "F - test-convert-read-from-stream-with-correct-payload-size/14")
11367     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                  "F - test-convert-read-from-stream-with-correct-payload-size/15")
11368     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"          "F - test-convert-read-from-stream-with-correct-payload-size/16")
11369     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                 "F - test-convert-read-from-stream-with-correct-payload-size/17")
11370     (check-next-stream-line-equal _test-output-stream "  c3/return"                     "F - test-convert-read-from-stream-with-correct-payload-size/18")
11371     # . epilogue
11372     89/<- %esp 5/r32/ebp
11373     5d/pop-to-ebp
11374     c3/return
11375 
11376 test-read-from-stream-with-non-stream-atom-base-type:
11377     # . prologue
11378     55/push-ebp
11379     89/<- %ebp 4/r32/esp
11380     # setup
11381     (clear-stream _test-input-stream)
11382     (clear-stream $_test-input-buffered-file->buffer)
11383     (clear-stream _test-output-stream)
11384     (clear-stream $_test-output-buffered-file->buffer)
11385     (clear-stream _test-error-stream)
11386     (clear-stream $_test-error-buffered-file->buffer)
11387     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11388     68/push 0/imm32
11389     68/push 0/imm32
11390     89/<- %edx 4/r32/esp
11391     (tailor-exit-descriptor %edx 0x10)
11392     #
11393     (write _test-input-stream "fn foo {\n")
11394     (write _test-input-stream "  var a: int\n")
11395     (write _test-input-stream "  read-from-stream a, 0\n")
11396     (write _test-input-stream "}\n")
11397     # convert
11398     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11399     # registers except esp clobbered at this point
11400     # restore ed
11401     89/<- %edx 4/r32/esp
11402     (flush _test-output-buffered-file)
11403     (flush _test-error-buffered-file)
11404 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
11410     # check output
11411     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-non-stream-atom-base-type: output should be empty")
11412     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt read-from-stream: var 'a' must be an addr to a stream"  "F - test-read-from-stream-with-non-stream-atom-base-type: error message")
11413     # check that stop(1) was called
11414     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-non-stream-atom-base-type: exit status")
11415     # don't restore from ebp
11416     81 0/subop/add %esp 8/imm32
11417     # . epilogue
11418     5d/pop-to-ebp
11419     c3/return
11420 
11421 test-read-from-stream-with-non-stream-compound-base-type:
11422     # . prologue
11423     55/push-ebp
11424     89/<- %ebp 4/r32/esp
11425     # setup
11426     (clear-stream _test-input-stream)
11427     (clear-stream $_test-input-buffered-file->buffer)
11428     (clear-stream _test-output-stream)
11429     (clear-stream $_test-output-buffered-file->buffer)
11430     (clear-stream _test-error-stream)
11431     (clear-stream $_test-error-buffered-file->buffer)
11432     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11433     68/push 0/imm32
11434     68/push 0/imm32
11435     89/<- %edx 4/r32/esp
11436     (tailor-exit-descriptor %edx 0x10)
11437     #
11438     (write _test-input-stream "fn foo {\n")
11439     (write _test-input-stream "  var a: (handle int)\n")
11440     (write _test-input-stream "  read-from-stream a, 0\n")
11441     (write _test-input-stream "}\n")
11442     # convert
11443     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11444     # registers except esp clobbered at this point
11445     # restore ed
11446     89/<- %edx 4/r32/esp
11447     (flush _test-output-buffered-file)
11448     (flush _test-error-buffered-file)
11449 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
11455     # check output
11456     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-non-stream-compound-base-type: output should be empty")
11457     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt read-from-stream: var 'a' must be an addr to a stream"  "F - test-read-from-stream-with-non-stream-compound-base-type: error message")
11458     # check that stop(1) was called
11459     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-non-stream-compound-base-type: exit status")
11460     # don't restore from ebp
11461     81 0/subop/add %esp 8/imm32
11462     # . epilogue
11463     5d/pop-to-ebp
11464     c3/return
11465 
11466 test-read-from-stream-with-non-stream-compound-base-type-2:
11467     # . prologue
11468     55/push-ebp
11469     89/<- %ebp 4/r32/esp
11470     # setup
11471     (clear-stream _test-input-stream)
11472     (clear-stream $_test-input-buffered-file->buffer)
11473     (clear-stream _test-output-stream)
11474     (clear-stream $_test-output-buffered-file->buffer)
11475     (clear-stream _test-error-stream)
11476     (clear-stream $_test-error-buffered-file->buffer)
11477     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11478     68/push 0/imm32
11479     68/push 0/imm32
11480     89/<- %edx 4/r32/esp
11481     (tailor-exit-descriptor %edx 0x10)
11482     #
11483     (write _test-input-stream "fn foo {\n")
11484     (write _test-input-stream "  var a: (addr int)\n")
11485     (write _test-input-stream "  read-from-stream a, 0\n")
11486     (write _test-input-stream "}\n")
11487     # convert
11488     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11489     # registers except esp clobbered at this point
11490     # restore ed
11491     89/<- %edx 4/r32/esp
11492     (flush _test-output-buffered-file)
11493     (flush _test-error-buffered-file)
11494 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
11500     # check output
11501     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-non-stream-compound-base-type-2: output should be empty")
11502     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt read-from-stream: var 'a' must be an addr to a stream"  "F - test-read-from-stream-with-non-stream-compound-base-type-2: error message")
11503     # check that stop(1) was called
11504     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-non-stream-compound-base-type-2: exit status")
11505     # don't restore from ebp
11506     81 0/subop/add %esp 8/imm32
11507     # . epilogue
11508     5d/pop-to-ebp
11509     c3/return
11510 
11511 test-read-from-stream-with-stream-atom-base-type:
11512     # . prologue
11513     55/push-ebp
11514     89/<- %ebp 4/r32/esp
11515     # setup
11516     (clear-stream _test-input-stream)
11517     (clear-stream $_test-input-buffered-file->buffer)
11518     (clear-stream _test-output-stream)
11519     (clear-stream $_test-output-buffered-file->buffer)
11520     (clear-stream _test-error-stream)
11521     (clear-stream $_test-error-buffered-file->buffer)
11522     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11523     68/push 0/imm32
11524     68/push 0/imm32
11525     89/<- %edx 4/r32/esp
11526     (tailor-exit-descriptor %edx 0x10)
11527     #
11528     (write _test-input-stream "fn foo {\n")
11529     (write _test-input-stream "  var a: stream\n")
11530     (write _test-input-stream "  read-from-stream a, 0\n")
11531     (write _test-input-stream "}\n")
11532     # convert
11533     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11534     # registers except esp clobbered at this point
11535     # restore ed
11536     89/<- %edx 4/r32/esp
11537     (flush _test-output-buffered-file)
11538     (flush _test-error-buffered-file)
11539 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
11545     # check output
11546     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-stream-atom-base-type: output should be empty")
11547     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt read-from-stream: var 'a' must be an addr to a stream"  "F - test-read-from-stream-with-stream-atom-base-type: error message")
11548     # check that stop(1) was called
11549     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-stream-atom-base-type: exit status")
11550     # don't restore from ebp
11551     81 0/subop/add %esp 8/imm32
11552     # . epilogue
11553     5d/pop-to-ebp
11554     c3/return
11555 
11556 test-read-from-stream-with-wrong-index-type:
11557     # . prologue
11558     55/push-ebp
11559     89/<- %ebp 4/r32/esp
11560     # setup
11561     (clear-stream _test-input-stream)
11562     (clear-stream $_test-input-buffered-file->buffer)
11563     (clear-stream _test-output-stream)
11564     (clear-stream $_test-output-buffered-file->buffer)
11565     (clear-stream _test-error-stream)
11566     (clear-stream $_test-error-buffered-file->buffer)
11567     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11568     68/push 0/imm32
11569     68/push 0/imm32
11570     89/<- %edx 4/r32/esp
11571     (tailor-exit-descriptor %edx 0x10)
11572     #
11573     (write _test-input-stream "fn foo {\n")
11574     (write _test-input-stream "  var a/eax: (addr stream int) <- copy 0\n")
11575     (write _test-input-stream "  var b: boolean\n")
11576     (write _test-input-stream "  read-from-stream a, b\n")
11577     (write _test-input-stream "}\n")
11578     # convert
11579     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11580     # registers except esp clobbered at this point
11581     # restore ed
11582     89/<- %edx 4/r32/esp
11583     (flush _test-output-buffered-file)
11584     (flush _test-error-buffered-file)
11585 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
11591     # check output
11592     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-wrong-index-type: output should be empty")
11593     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt read-from-stream: target 'b' must be an addr"  "F - test-read-from-stream-with-wrong-index-type: error message")
11594     # check that stop(1) was called
11595     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-wrong-index-type: exit status")
11596     # don't restore from ebp
11597     81 0/subop/add %esp 8/imm32
11598     # . epilogue
11599     5d/pop-to-ebp
11600     c3/return
11601 
11602 test-read-from-stream-with-no-inouts:
11603     # . prologue
11604     55/push-ebp
11605     89/<- %ebp 4/r32/esp
11606     # setup
11607     (clear-stream _test-input-stream)
11608     (clear-stream $_test-input-buffered-file->buffer)
11609     (clear-stream _test-output-stream)
11610     (clear-stream $_test-output-buffered-file->buffer)
11611     (clear-stream _test-error-stream)
11612     (clear-stream $_test-error-buffered-file->buffer)
11613     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11614     68/push 0/imm32
11615     68/push 0/imm32
11616     89/<- %edx 4/r32/esp
11617     (tailor-exit-descriptor %edx 0x10)
11618     #
11619     (write _test-input-stream "fn foo {\n")
11620     (write _test-input-stream "  read-from-stream\n")
11621     (write _test-input-stream "}\n")
11622     # convert
11623     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11624     # registers except esp clobbered at this point
11625     # restore ed
11626     89/<- %edx 4/r32/esp
11627     (flush _test-output-buffered-file)
11628     (flush _test-error-buffered-file)
11629 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
11635     # check output
11636     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-no-inouts: output should be empty")
11637     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt read-from-stream: too few inouts (2 required)"  "F - test-read-from-stream-with-no-inouts: error message")
11638     # check that stop(1) was called
11639     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-no-inouts: exit status")
11640     # don't restore from ebp
11641     81 0/subop/add %esp 8/imm32
11642     # . epilogue
11643     5d/pop-to-ebp
11644     c3/return
11645 
11646 test-read-from-stream-with-too-few-inouts:
11647     # . prologue
11648     55/push-ebp
11649     89/<- %ebp 4/r32/esp
11650     # setup
11651     (clear-stream _test-input-stream)
11652     (clear-stream $_test-input-buffered-file->buffer)
11653     (clear-stream _test-output-stream)
11654     (clear-stream $_test-output-buffered-file->buffer)
11655     (clear-stream _test-error-stream)
11656     (clear-stream $_test-error-buffered-file->buffer)
11657     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11658     68/push 0/imm32
11659     68/push 0/imm32
11660     89/<- %edx 4/r32/esp
11661     (tailor-exit-descriptor %edx 0x10)
11662     #
11663     (write _test-input-stream "fn foo {\n")
11664     (write _test-input-stream "  var a: (addr stream int)\n")
11665     (write _test-input-stream "  read-from-stream a\n")
11666     (write _test-input-stream "}\n")
11667     # convert
11668     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11669     # registers except esp clobbered at this point
11670     # restore ed
11671     89/<- %edx 4/r32/esp
11672     (flush _test-output-buffered-file)
11673     (flush _test-error-buffered-file)
11674 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
11680     # check output
11681     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-too-few-inouts: output should be empty")
11682     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt read-from-stream: too few inouts (2 required)"  "F - test-read-from-stream-with-too-few-inouts: error message")
11683     # check that stop(1) was called
11684     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-too-few-inouts: exit status")
11685     # don't restore from ebp
11686     81 0/subop/add %esp 8/imm32
11687     # . epilogue
11688     5d/pop-to-ebp
11689     c3/return
11690 
11691 test-read-from-stream-with-too-many-inouts:
11692     # . prologue
11693     55/push-ebp
11694     89/<- %ebp 4/r32/esp
11695     # setup
11696     (clear-stream _test-input-stream)
11697     (clear-stream $_test-input-buffered-file->buffer)
11698     (clear-stream _test-output-stream)
11699     (clear-stream $_test-output-buffered-file->buffer)
11700     (clear-stream _test-error-stream)
11701     (clear-stream $_test-error-buffered-file->buffer)
11702     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11703     68/push 0/imm32
11704     68/push 0/imm32
11705     89/<- %edx 4/r32/esp
11706     (tailor-exit-descriptor %edx 0x10)
11707     #
11708     (write _test-input-stream "fn foo {\n")
11709     (write _test-input-stream "  var a: (addr stream int)\n")
11710     (write _test-input-stream "  var b: (addr int)\n")
11711     (write _test-input-stream "  read-from-stream a, b, 0\n")
11712     (write _test-input-stream "}\n")
11713     # convert
11714     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11715     # registers except esp clobbered at this point
11716     # restore ed
11717     89/<- %edx 4/r32/esp
11718     (flush _test-output-buffered-file)
11719     (flush _test-error-buffered-file)
11720 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
11726     # check output
11727     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-too-many-inouts: output should be empty")
11728     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt read-from-stream: too many inouts (2 required)"  "F - test-read-from-stream-with-too-many-inouts: error message")
11729     # check that stop(1) was called
11730     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-too-many-inouts: exit status")
11731     # don't restore from ebp
11732     81 0/subop/add %esp 8/imm32
11733     # . epilogue
11734     5d/pop-to-ebp
11735     c3/return
11736 
11737 test-read-from-stream-with-output:
11738     # . prologue
11739     55/push-ebp
11740     89/<- %ebp 4/r32/esp
11741     # setup
11742     (clear-stream _test-input-stream)
11743     (clear-stream $_test-input-buffered-file->buffer)
11744     (clear-stream _test-output-stream)
11745     (clear-stream $_test-output-buffered-file->buffer)
11746     (clear-stream _test-error-stream)
11747     (clear-stream $_test-error-buffered-file->buffer)
11748     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11749     68/push 0/imm32
11750     68/push 0/imm32
11751     89/<- %edx 4/r32/esp
11752     (tailor-exit-descriptor %edx 0x10)
11753     #
11754     (write _test-input-stream "fn foo {\n")
11755     (write _test-input-stream "  var a: (addr stream int)\n")
11756     (write _test-input-stream "  var b/eax: (addr int) <- copy 0\n")
11757     (write _test-input-stream "  b <- read-from-stream a, b\n")
11758     (write _test-input-stream "}\n")
11759     # convert
11760     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11761     # registers except esp clobbered at this point
11762     # restore ed
11763     89/<- %edx 4/r32/esp
11764     (flush _test-output-buffered-file)
11765     (flush _test-error-buffered-file)
11766 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
11772     # check output
11773     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-output: output should be empty")
11774     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt read-from-stream: unexpected output"  "F - test-read-from-stream-with-output: error message")
11775     # check that stop(1) was called
11776     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-output: exit status")
11777     # don't restore from ebp
11778     81 0/subop/add %esp 8/imm32
11779     # . epilogue
11780     5d/pop-to-ebp
11781     c3/return
11782 
11783 test-convert-write-to-stream:
11784     # . prologue
11785     55/push-ebp
11786     89/<- %ebp 4/r32/esp
11787     # setup
11788     (clear-stream _test-input-stream)
11789     (clear-stream $_test-input-buffered-file->buffer)
11790     (clear-stream _test-output-stream)
11791     (clear-stream $_test-output-buffered-file->buffer)
11792     #
11793     (write _test-input-stream "fn foo {\n")
11794     (write _test-input-stream "  var s/esi: (addr stream int) <- copy 0\n")
11795     (write _test-input-stream "  var o/ecx: (addr int) <- copy 0\n")
11796     (write _test-input-stream "  write-to-stream s, o\n")
11797     (write _test-input-stream "}\n")
11798     # convert
11799     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
11800     # registers except esp clobbered at this point
11801     # restore ed
11802     89/<- %edx 4/r32/esp
11803     (flush _test-output-buffered-file)
11804     (flush _test-error-buffered-file)
11805 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
11811     # check output
11812     (check-next-stream-line-equal _test-output-stream "foo:"                            "F - test-convert-write-to-stream/0")
11813     (check-next-stream-line-equal _test-output-stream "  # . prologue"                  "F - test-convert-write-to-stream/1")
11814     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                   "F - test-convert-write-to-stream/2")
11815     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"          "F - test-convert-write-to-stream/3")
11816     (check-next-stream-line-equal _test-output-stream "  {"                             "F - test-convert-write-to-stream/4")
11817     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"           "F - test-convert-write-to-stream/5")
11818     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %esi"        "F - test-convert-write-to-stream/6")
11819     (check-next-stream-line-equal _test-output-stream "    be/copy-to-esi 0/imm32"      "F - test-convert-write-to-stream/7")
11820     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"        "F - test-convert-write-to-stream/8")
11821     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"      "F - test-convert-write-to-stream/9")
11822     (check-next-stream-line-equal _test-output-stream "    (write-to-stream %esi %ecx 0x00000004)"  "F - test-convert-write-to-stream/10")
11823     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-write-to-stream/11")
11824     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %esi"         "F - test-convert-write-to-stream/12")
11825     (check-next-stream-line-equal _test-output-stream "  }"                             "F - test-convert-write-to-stream/13")
11826     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"          "F - test-convert-write-to-stream/14")
11827     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                  "F - test-convert-write-to-stream/15")
11828     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"          "F - test-convert-write-to-stream/16")
11829     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                 "F - test-convert-write-to-stream/17")
11830     (check-next-stream-line-equal _test-output-stream "  c3/return"                     "F - test-convert-write-to-stream/18")
11831     # . epilogue
11832     89/<- %esp 5/r32/ebp
11833     5d/pop-to-ebp
11834     c3/return
11835 
11836 test-convert-write-to-stream-with-correct-payload-size:
11837     # . prologue
11838     55/push-ebp
11839     89/<- %ebp 4/r32/esp
11840     # setup
11841     (clear-stream _test-input-stream)
11842     (clear-stream $_test-input-buffered-file->buffer)
11843     (clear-stream _test-output-stream)
11844     (clear-stream $_test-output-buffered-file->buffer)
11845     #
11846     (write _test-input-stream "fn foo {\n")
11847     (write _test-input-stream "  var s/esi: (addr stream handle int) <- copy 0\n")
11848     (write _test-input-stream "  var o/ecx: (addr handle int) <- copy 0\n")
11849     (write _test-input-stream "  write-to-stream s, o\n")
11850     (write _test-input-stream "}\n")
11851     # convert
11852     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
11853     # registers except esp clobbered at this point
11854     # restore ed
11855     89/<- %edx 4/r32/esp
11856     (flush _test-output-buffered-file)
11857     (flush _test-error-buffered-file)
11858 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
11864     # check output
11865     (check-next-stream-line-equal _test-output-stream "foo:"                            "F - test-convert-write-to-stream-with-correct-payload-size/0")
11866     (check-next-stream-line-equal _test-output-stream "  # . prologue"                  "F - test-convert-write-to-stream-with-correct-payload-size/1")
11867     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                   "F - test-convert-write-to-stream-with-correct-payload-size/2")
11868     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"          "F - test-convert-write-to-stream-with-correct-payload-size/3")
11869     (check-next-stream-line-equal _test-output-stream "  {"                             "F - test-convert-write-to-stream-with-correct-payload-size/4")
11870     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"           "F - test-convert-write-to-stream-with-correct-payload-size/5")
11871     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %esi"        "F - test-convert-write-to-stream-with-correct-payload-size/6")
11872     (check-next-stream-line-equal _test-output-stream "    be/copy-to-esi 0/imm32"      "F - test-convert-write-to-stream-with-correct-payload-size/7")
11873     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"        "F - test-convert-write-to-stream-with-correct-payload-size/8")
11874     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"      "F - test-convert-write-to-stream-with-correct-payload-size/9")
11875     (check-next-stream-line-equal _test-output-stream "    (write-to-stream %esi %ecx 0x00000008)"  "F - test-convert-write-to-stream-with-correct-payload-size/10")
11876     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-write-to-stream-with-correct-payload-size/11")
11877     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %esi"         "F - test-convert-write-to-stream-with-correct-payload-size/12")
11878     (check-next-stream-line-equal _test-output-stream "  }"                             "F - test-convert-write-to-stream-with-correct-payload-size/13")
11879     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"          "F - test-convert-write-to-stream-with-correct-payload-size/14")
11880     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                  "F - test-convert-write-to-stream-with-correct-payload-size/15")
11881     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"          "F - test-convert-write-to-stream-with-correct-payload-size/16")
11882     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                 "F - test-convert-write-to-stream-with-correct-payload-size/17")
11883     (check-next-stream-line-equal _test-output-stream "  c3/return"                     "F - test-convert-write-to-stream-with-correct-payload-size/18")
11884     # . epilogue
11885     89/<- %esp 5/r32/ebp
11886     5d/pop-to-ebp
11887     c3/return
11888 
11889 test-write-to-stream-with-non-stream-atom-base-type:
11890     # . prologue
11891     55/push-ebp
11892     89/<- %ebp 4/r32/esp
11893     # setup
11894     (clear-stream _test-input-stream)
11895     (clear-stream $_test-input-buffered-file->buffer)
11896     (clear-stream _test-output-stream)
11897     (clear-stream $_test-output-buffered-file->buffer)
11898     (clear-stream _test-error-stream)
11899     (clear-stream $_test-error-buffered-file->buffer)
11900     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11901     68/push 0/imm32
11902     68/push 0/imm32
11903     89/<- %edx 4/r32/esp
11904     (tailor-exit-descriptor %edx 0x10)
11905     #
11906     (write _test-input-stream "fn foo {\n")
11907     (write _test-input-stream "  var a: int\n")
11908     (write _test-input-stream "  write-to-stream a, 0\n")
11909     (write _test-input-stream "}\n")
11910     # convert
11911     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11912     # registers except esp clobbered at this point
11913     # restore ed
11914     89/<- %edx 4/r32/esp
11915     (flush _test-output-buffered-file)
11916     (flush _test-error-buffered-file)
11917 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
11923     # check output
11924     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-non-stream-atom-base-type: output should be empty")
11925     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt write-to-stream: var 'a' must be an addr to a stream"  "F - test-write-to-stream-with-non-stream-atom-base-type: error message")
11926     # check that stop(1) was called
11927     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-non-stream-atom-base-type: exit status")
11928     # don't restore from ebp
11929     81 0/subop/add %esp 8/imm32
11930     # . epilogue
11931     5d/pop-to-ebp
11932     c3/return
11933 
11934 test-write-to-stream-with-non-stream-compound-base-type:
11935     # . prologue
11936     55/push-ebp
11937     89/<- %ebp 4/r32/esp
11938     # setup
11939     (clear-stream _test-input-stream)
11940     (clear-stream $_test-input-buffered-file->buffer)
11941     (clear-stream _test-output-stream)
11942     (clear-stream $_test-output-buffered-file->buffer)
11943     (clear-stream _test-error-stream)
11944     (clear-stream $_test-error-buffered-file->buffer)
11945     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11946     68/push 0/imm32
11947     68/push 0/imm32
11948     89/<- %edx 4/r32/esp
11949     (tailor-exit-descriptor %edx 0x10)
11950     #
11951     (write _test-input-stream "fn foo {\n")
11952     (write _test-input-stream "  var a: (handle int)\n")
11953     (write _test-input-stream "  write-to-stream a, 0\n")
11954     (write _test-input-stream "}\n")
11955     # convert
11956     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
11957     # registers except esp clobbered at this point
11958     # restore ed
11959     89/<- %edx 4/r32/esp
11960     (flush _test-output-buffered-file)
11961     (flush _test-error-buffered-file)
11962 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
11968     # check output
11969     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-non-stream-compound-base-type: output should be empty")
11970     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt write-to-stream: var 'a' must be an addr to a stream"  "F - test-write-to-stream-with-non-stream-compound-base-type: error message")
11971     # check that stop(1) was called
11972     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-non-stream-compound-base-type: exit status")
11973     # don't restore from ebp
11974     81 0/subop/add %esp 8/imm32
11975     # . epilogue
11976     5d/pop-to-ebp
11977     c3/return
11978 
11979 test-write-to-stream-with-non-stream-compound-base-type-2:
11980     # . prologue
11981     55/push-ebp
11982     89/<- %ebp 4/r32/esp
11983     # setup
11984     (clear-stream _test-input-stream)
11985     (clear-stream $_test-input-buffered-file->buffer)
11986     (clear-stream _test-output-stream)
11987     (clear-stream $_test-output-buffered-file->buffer)
11988     (clear-stream _test-error-stream)
11989     (clear-stream $_test-error-buffered-file->buffer)
11990     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
11991     68/push 0/imm32
11992     68/push 0/imm32
11993     89/<- %edx 4/r32/esp
11994     (tailor-exit-descriptor %edx 0x10)
11995     #
11996     (write _test-input-stream "fn foo {\n")
11997     (write _test-input-stream "  var a: (addr int)\n")
11998     (write _test-input-stream "  write-to-stream a, 0\n")
11999     (write _test-input-stream "}\n")
12000     # convert
12001     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12002     # registers except esp clobbered at this point
12003     # restore ed
12004     89/<- %edx 4/r32/esp
12005     (flush _test-output-buffered-file)
12006     (flush _test-error-buffered-file)
12007 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
12013     # check output
12014     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-non-stream-compound-base-type-2: output should be empty")
12015     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt write-to-stream: var 'a' must be an addr to a stream"  "F - test-write-to-stream-with-non-stream-compound-base-type-2: error message")
12016     # check that stop(1) was called
12017     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-non-stream-compound-base-type-2: exit status")
12018     # don't restore from ebp
12019     81 0/subop/add %esp 8/imm32
12020     # . epilogue
12021     5d/pop-to-ebp
12022     c3/return
12023 
12024 test-write-to-stream-with-stream-atom-base-type:
12025     # . prologue
12026     55/push-ebp
12027     89/<- %ebp 4/r32/esp
12028     # setup
12029     (clear-stream _test-input-stream)
12030     (clear-stream $_test-input-buffered-file->buffer)
12031     (clear-stream _test-output-stream)
12032     (clear-stream $_test-output-buffered-file->buffer)
12033     (clear-stream _test-error-stream)
12034     (clear-stream $_test-error-buffered-file->buffer)
12035     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12036     68/push 0/imm32
12037     68/push 0/imm32
12038     89/<- %edx 4/r32/esp
12039     (tailor-exit-descriptor %edx 0x10)
12040     #
12041     (write _test-input-stream "fn foo {\n")
12042     (write _test-input-stream "  var a: stream\n")
12043     (write _test-input-stream "  write-to-stream a, 0\n")
12044     (write _test-input-stream "}\n")
12045     # convert
12046     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12047     # registers except esp clobbered at this point
12048     # restore ed
12049     89/<- %edx 4/r32/esp
12050     (flush _test-output-buffered-file)
12051     (flush _test-error-buffered-file)
12052 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
12058     # check output
12059     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-stream-atom-base-type: output should be empty")
12060     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt write-to-stream: var 'a' must be an addr to a stream"  "F - test-write-to-stream-with-stream-atom-base-type: error message")
12061     # check that stop(1) was called
12062     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-stream-atom-base-type: exit status")
12063     # don't restore from ebp
12064     81 0/subop/add %esp 8/imm32
12065     # . epilogue
12066     5d/pop-to-ebp
12067     c3/return
12068 
12069 test-write-to-stream-with-wrong-index-type:
12070     # . prologue
12071     55/push-ebp
12072     89/<- %ebp 4/r32/esp
12073     # setup
12074     (clear-stream _test-input-stream)
12075     (clear-stream $_test-input-buffered-file->buffer)
12076     (clear-stream _test-output-stream)
12077     (clear-stream $_test-output-buffered-file->buffer)
12078     (clear-stream _test-error-stream)
12079     (clear-stream $_test-error-buffered-file->buffer)
12080     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12081     68/push 0/imm32
12082     68/push 0/imm32
12083     89/<- %edx 4/r32/esp
12084     (tailor-exit-descriptor %edx 0x10)
12085     #
12086     (write _test-input-stream "fn foo {\n")
12087     (write _test-input-stream "  var a/eax: (addr stream int) <- copy 0\n")
12088     (write _test-input-stream "  var b: boolean\n")
12089     (write _test-input-stream "  write-to-stream a, b\n")
12090     (write _test-input-stream "}\n")
12091     # convert
12092     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12093     # registers except esp clobbered at this point
12094     # restore ed
12095     89/<- %edx 4/r32/esp
12096     (flush _test-output-buffered-file)
12097     (flush _test-error-buffered-file)
12098 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
12104     # check output
12105     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-wrong-index-type: output should be empty")
12106     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt write-to-stream: target 'b' must be an addr"  "F - test-write-to-stream-with-wrong-index-type: error message")
12107     # check that stop(1) was called
12108     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-wrong-index-type: exit status")
12109     # don't restore from ebp
12110     81 0/subop/add %esp 8/imm32
12111     # . epilogue
12112     5d/pop-to-ebp
12113     c3/return
12114 
12115 test-write-to-stream-with-no-inouts:
12116     # . prologue
12117     55/push-ebp
12118     89/<- %ebp 4/r32/esp
12119     # setup
12120     (clear-stream _test-input-stream)
12121     (clear-stream $_test-input-buffered-file->buffer)
12122     (clear-stream _test-output-stream)
12123     (clear-stream $_test-output-buffered-file->buffer)
12124     (clear-stream _test-error-stream)
12125     (clear-stream $_test-error-buffered-file->buffer)
12126     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12127     68/push 0/imm32
12128     68/push 0/imm32
12129     89/<- %edx 4/r32/esp
12130     (tailor-exit-descriptor %edx 0x10)
12131     #
12132     (write _test-input-stream "fn foo {\n")
12133     (write _test-input-stream "  write-to-stream\n")
12134     (write _test-input-stream "}\n")
12135     # convert
12136     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12137     # registers except esp clobbered at this point
12138     # restore ed
12139     89/<- %edx 4/r32/esp
12140     (flush _test-output-buffered-file)
12141     (flush _test-error-buffered-file)
12142 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
12148     # check output
12149     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-no-inouts: output should be empty")
12150     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt write-to-stream: too few inouts (2 required)"  "F - test-write-to-stream-with-no-inouts: error message")
12151     # check that stop(1) was called
12152     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-no-inouts: exit status")
12153     # don't restore from ebp
12154     81 0/subop/add %esp 8/imm32
12155     # . epilogue
12156     5d/pop-to-ebp
12157     c3/return
12158 
12159 test-write-to-stream-with-too-few-inouts:
12160     # . prologue
12161     55/push-ebp
12162     89/<- %ebp 4/r32/esp
12163     # setup
12164     (clear-stream _test-input-stream)
12165     (clear-stream $_test-input-buffered-file->buffer)
12166     (clear-stream _test-output-stream)
12167     (clear-stream $_test-output-buffered-file->buffer)
12168     (clear-stream _test-error-stream)
12169     (clear-stream $_test-error-buffered-file->buffer)
12170     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12171     68/push 0/imm32
12172     68/push 0/imm32
12173     89/<- %edx 4/r32/esp
12174     (tailor-exit-descriptor %edx 0x10)
12175     #
12176     (write _test-input-stream "fn foo {\n")
12177     (write _test-input-stream "  var a: (addr stream int)\n")
12178     (write _test-input-stream "  write-to-stream a\n")
12179     (write _test-input-stream "}\n")
12180     # convert
12181     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12182     # registers except esp clobbered at this point
12183     # restore ed
12184     89/<- %edx 4/r32/esp
12185     (flush _test-output-buffered-file)
12186     (flush _test-error-buffered-file)
12187 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
12193     # check output
12194     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-too-few-inouts: output should be empty")
12195     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt write-to-stream: too few inouts (2 required)"  "F - test-write-to-stream-with-too-few-inouts: error message")
12196     # check that stop(1) was called
12197     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-too-few-inouts: exit status")
12198     # don't restore from ebp
12199     81 0/subop/add %esp 8/imm32
12200     # . epilogue
12201     5d/pop-to-ebp
12202     c3/return
12203 
12204 test-write-to-stream-with-too-many-inouts:
12205     # . prologue
12206     55/push-ebp
12207     89/<- %ebp 4/r32/esp
12208     # setup
12209     (clear-stream _test-input-stream)
12210     (clear-stream $_test-input-buffered-file->buffer)
12211     (clear-stream _test-output-stream)
12212     (clear-stream $_test-output-buffered-file->buffer)
12213     (clear-stream _test-error-stream)
12214     (clear-stream $_test-error-buffered-file->buffer)
12215     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12216     68/push 0/imm32
12217     68/push 0/imm32
12218     89/<- %edx 4/r32/esp
12219     (tailor-exit-descriptor %edx 0x10)
12220     #
12221     (write _test-input-stream "fn foo {\n")
12222     (write _test-input-stream "  var a: (addr stream int)\n")
12223     (write _test-input-stream "  var b: (addr int)\n")
12224     (write _test-input-stream "  write-to-stream a, b, 0\n")
12225     (write _test-input-stream "}\n")
12226     # convert
12227     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12228     # registers except esp clobbered at this point
12229     # restore ed
12230     89/<- %edx 4/r32/esp
12231     (flush _test-output-buffered-file)
12232     (flush _test-error-buffered-file)
12233 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
12239     # check output
12240     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-too-many-inouts: output should be empty")
12241     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt write-to-stream: too many inouts (2 required)"  "F - test-write-to-stream-with-too-many-inouts: error message")
12242     # check that stop(1) was called
12243     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-too-many-inouts: exit status")
12244     # don't restore from ebp
12245     81 0/subop/add %esp 8/imm32
12246     # . epilogue
12247     5d/pop-to-ebp
12248     c3/return
12249 
12250 test-write-to-stream-with-output:
12251     # . prologue
12252     55/push-ebp
12253     89/<- %ebp 4/r32/esp
12254     # setup
12255     (clear-stream _test-input-stream)
12256     (clear-stream $_test-input-buffered-file->buffer)
12257     (clear-stream _test-output-stream)
12258     (clear-stream $_test-output-buffered-file->buffer)
12259     (clear-stream _test-error-stream)
12260     (clear-stream $_test-error-buffered-file->buffer)
12261     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12262     68/push 0/imm32
12263     68/push 0/imm32
12264     89/<- %edx 4/r32/esp
12265     (tailor-exit-descriptor %edx 0x10)
12266     #
12267     (write _test-input-stream "fn foo {\n")
12268     (write _test-input-stream "  var a: (addr stream int)\n")
12269     (write _test-input-stream "  var b/eax: (addr int) <- copy 0\n")
12270     (write _test-input-stream "  b <- write-to-stream a, b\n")
12271     (write _test-input-stream "}\n")
12272     # convert
12273     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12274     # registers except esp clobbered at this point
12275     # restore ed
12276     89/<- %edx 4/r32/esp
12277     (flush _test-output-buffered-file)
12278     (flush _test-error-buffered-file)
12279 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
12285     # check output
12286     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-output: output should be empty")
12287     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt write-to-stream: unexpected output"  "F - test-write-to-stream-with-output: error message")
12288     # check that stop(1) was called
12289     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-output: exit status")
12290     # don't restore from ebp
12291     81 0/subop/add %esp 8/imm32
12292     # . epilogue
12293     5d/pop-to-ebp
12294     c3/return
12295 
12296 test-length-with-non-array-atom-base-type:
12297     # . prologue
12298     55/push-ebp
12299     89/<- %ebp 4/r32/esp
12300     # setup
12301     (clear-stream _test-input-stream)
12302     (clear-stream $_test-input-buffered-file->buffer)
12303     (clear-stream _test-output-stream)
12304     (clear-stream $_test-output-buffered-file->buffer)
12305     (clear-stream _test-error-stream)
12306     (clear-stream $_test-error-buffered-file->buffer)
12307     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12308     68/push 0/imm32
12309     68/push 0/imm32
12310     89/<- %edx 4/r32/esp
12311     (tailor-exit-descriptor %edx 0x10)
12312     #
12313     (write _test-input-stream "fn foo {\n")
12314     (write _test-input-stream "  var a: int\n")
12315     (write _test-input-stream "  var c/ecx: int <- length a\n")
12316     (write _test-input-stream "}\n")
12317     # convert
12318     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12319     # registers except esp clobbered at this point
12320     # restore ed
12321     89/<- %edx 4/r32/esp
12322     (flush _test-output-buffered-file)
12323     (flush _test-error-buffered-file)
12324 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
12330     # check output
12331     (check-stream-equal _test-output-stream  ""  "F - test-length-with-non-array-atom-base-type: output should be empty")
12332     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt length: var 'a' is not an array"  "F - test-length-with-non-array-atom-base-type: error message")
12333     # check that stop(1) was called
12334     (check-ints-equal *(edx+4) 2 "F - test-length-with-non-array-atom-base-type: exit status")
12335     # don't restore from ebp
12336     81 0/subop/add %esp 8/imm32
12337     # . epilogue
12338     5d/pop-to-ebp
12339     c3/return
12340 
12341 test-length-with-non-array-compound-base-type:
12342     # . prologue
12343     55/push-ebp
12344     89/<- %ebp 4/r32/esp
12345     # setup
12346     (clear-stream _test-input-stream)
12347     (clear-stream $_test-input-buffered-file->buffer)
12348     (clear-stream _test-output-stream)
12349     (clear-stream $_test-output-buffered-file->buffer)
12350     (clear-stream _test-error-stream)
12351     (clear-stream $_test-error-buffered-file->buffer)
12352     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12353     68/push 0/imm32
12354     68/push 0/imm32
12355     89/<- %edx 4/r32/esp
12356     (tailor-exit-descriptor %edx 0x10)
12357     #
12358     (write _test-input-stream "fn foo {\n")
12359     (write _test-input-stream "  var a: (handle int)\n")
12360     (write _test-input-stream "  var c/ecx: (addr int) <- length a, 0\n")
12361     (write _test-input-stream "}\n")
12362     # convert
12363     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12364     # registers except esp clobbered at this point
12365     # restore ed
12366     89/<- %edx 4/r32/esp
12367     (flush _test-output-buffered-file)
12368     (flush _test-error-buffered-file)
12369 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
12375     # check output
12376     (check-stream-equal _test-output-stream  ""  "F - test-length-with-non-array-compound-base-type: output should be empty")
12377     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt length: var 'a' is not an array"  "F - test-length-with-non-array-compound-base-type: error message")
12378     # check that stop(1) was called
12379     (check-ints-equal *(edx+4) 2 "F - test-length-with-non-array-compound-base-type: exit status")
12380     # don't restore from ebp
12381     81 0/subop/add %esp 8/imm32
12382     # . epilogue
12383     5d/pop-to-ebp
12384     c3/return
12385 
12386 test-length-with-non-array-compound-base-type-2:
12387     # . prologue
12388     55/push-ebp
12389     89/<- %ebp 4/r32/esp
12390     # setup
12391     (clear-stream _test-input-stream)
12392     (clear-stream $_test-input-buffered-file->buffer)
12393     (clear-stream _test-output-stream)
12394     (clear-stream $_test-output-buffered-file->buffer)
12395     (clear-stream _test-error-stream)
12396     (clear-stream $_test-error-buffered-file->buffer)
12397     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12398     68/push 0/imm32
12399     68/push 0/imm32
12400     89/<- %edx 4/r32/esp
12401     (tailor-exit-descriptor %edx 0x10)
12402     #
12403     (write _test-input-stream "fn foo {\n")
12404     (write _test-input-stream "  var a: (addr int)\n")
12405     (write _test-input-stream "  var c/ecx: (addr int) <- length a, 0\n")
12406     (write _test-input-stream "}\n")
12407     # convert
12408     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12409     # registers except esp clobbered at this point
12410     # restore ed
12411     89/<- %edx 4/r32/esp
12412     (flush _test-output-buffered-file)
12413     (flush _test-error-buffered-file)
12414 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
12420     # check output
12421     (check-stream-equal _test-output-stream  ""  "F - test-length-with-non-array-compound-base-type-2: output should be empty")
12422     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt length: var 'a' is not an array"  "F - test-length-with-non-array-compound-base-type-2: error message")
12423     # check that stop(1) was called
12424     (check-ints-equal *(edx+4) 2 "F - test-length-with-non-array-compound-base-type-2: exit status")
12425     # don't restore from ebp
12426     81 0/subop/add %esp 8/imm32
12427     # . epilogue
12428     5d/pop-to-ebp
12429     c3/return
12430 
12431 test-length-with-array-atom-base-type:
12432     # . prologue
12433     55/push-ebp
12434     89/<- %ebp 4/r32/esp
12435     # setup
12436     (clear-stream _test-input-stream)
12437     (clear-stream $_test-input-buffered-file->buffer)
12438     (clear-stream _test-output-stream)
12439     (clear-stream $_test-output-buffered-file->buffer)
12440     (clear-stream _test-error-stream)
12441     (clear-stream $_test-error-buffered-file->buffer)
12442     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12443     68/push 0/imm32
12444     68/push 0/imm32
12445     89/<- %edx 4/r32/esp
12446     (tailor-exit-descriptor %edx 0x10)
12447     #
12448     (write _test-input-stream "fn foo {\n")
12449     (write _test-input-stream "  var a: array\n")
12450     (write _test-input-stream "  var c/ecx: (addr int) <- length a\n")
12451     (write _test-input-stream "}\n")
12452     # convert
12453     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12454     # registers except esp clobbered at this point
12455     # restore ed
12456     89/<- %edx 4/r32/esp
12457     (flush _test-output-buffered-file)
12458     (flush _test-error-buffered-file)
12459 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
12465     # check output
12466     (check-stream-equal _test-output-stream  ""  "F - test-length-with-array-atom-base-type: output should be empty")
12467     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt length: array 'a' must specify the type of its elements"  "F - test-length-with-array-atom-base-type: error message")
12468     # check that stop(1) was called
12469     (check-ints-equal *(edx+4) 2 "F - test-length-with-array-atom-base-type: exit status")
12470     # don't restore from ebp
12471     81 0/subop/add %esp 8/imm32
12472     # . epilogue
12473     5d/pop-to-ebp
12474     c3/return
12475 
12476 test-length-with-addr-base-on-stack:
12477     # . prologue
12478     55/push-ebp
12479     89/<- %ebp 4/r32/esp
12480     # setup
12481     (clear-stream _test-input-stream)
12482     (clear-stream $_test-input-buffered-file->buffer)
12483     (clear-stream _test-output-stream)
12484     (clear-stream $_test-output-buffered-file->buffer)
12485     (clear-stream _test-error-stream)
12486     (clear-stream $_test-error-buffered-file->buffer)
12487     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12488     68/push 0/imm32
12489     68/push 0/imm32
12490     89/<- %edx 4/r32/esp
12491     (tailor-exit-descriptor %edx 0x10)
12492     #
12493     (write _test-input-stream "fn foo {\n")
12494     (write _test-input-stream "  var a: (addr array int)\n")
12495     (write _test-input-stream "  var c/ecx: (addr int) <- length a\n")
12496     (write _test-input-stream "}\n")
12497     # convert
12498     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12499     # registers except esp clobbered at this point
12500     # restore ed
12501     89/<- %edx 4/r32/esp
12502     (flush _test-output-buffered-file)
12503     (flush _test-error-buffered-file)
12504 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
12510     # check output
12511     (check-stream-equal _test-output-stream  ""  "F - test-length-with-addr-base-on-stack: output should be empty")
12512     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt length: var 'a' is an addr to an array, and so must live in a register"  "F - test-length-with-addr-base-on-stack: error message")
12513     # check that stop(1) was called
12514     (check-ints-equal *(edx+4) 2 "F - test-length-with-addr-base-on-stack: exit status")
12515     # don't restore from ebp
12516     81 0/subop/add %esp 8/imm32
12517     # . epilogue
12518     5d/pop-to-ebp
12519     c3/return
12520 
12521 test-length-with-wrong-output-type:
12522     # . prologue
12523     55/push-ebp
12524     89/<- %ebp 4/r32/esp
12525     # setup
12526     (clear-stream _test-input-stream)
12527     (clear-stream $_test-input-buffered-file->buffer)
12528     (clear-stream _test-output-stream)
12529     (clear-stream $_test-output-buffered-file->buffer)
12530     (clear-stream _test-error-stream)
12531     (clear-stream $_test-error-buffered-file->buffer)
12532     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12533     68/push 0/imm32
12534     68/push 0/imm32
12535     89/<- %edx 4/r32/esp
12536     (tailor-exit-descriptor %edx 0x10)
12537     #
12538     (write _test-input-stream "fn foo {\n")
12539     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
12540     (write _test-input-stream "  var o/edi: (addr int) <- length a\n")
12541     (write _test-input-stream "}\n")
12542     # convert
12543     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12544     # registers except esp clobbered at this point
12545     # restore ed
12546     89/<- %edx 4/r32/esp
12547     (flush _test-output-buffered-file)
12548     (flush _test-error-buffered-file)
12549 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
12555     # check output
12556     (check-stream-equal _test-output-stream  ""  "F - test-length-with-wrong-output-type: output should be empty")
12557     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt length: output 'o' does not have the right type"  "F - test-length-with-wrong-output-type: error message")
12558     # check that stop(1) was called
12559     (check-ints-equal *(edx+4) 2 "F - test-length-with-wrong-output-type: exit status")
12560     # don't restore from ebp
12561     81 0/subop/add %esp 8/imm32
12562     # . epilogue
12563     5d/pop-to-ebp
12564     c3/return
12565 
12566 test-length-with-wrong-output-compound-type:
12567     # . prologue
12568     55/push-ebp
12569     89/<- %ebp 4/r32/esp
12570     # setup
12571     (clear-stream _test-input-stream)
12572     (clear-stream $_test-input-buffered-file->buffer)
12573     (clear-stream _test-output-stream)
12574     (clear-stream $_test-output-buffered-file->buffer)
12575     (clear-stream _test-error-stream)
12576     (clear-stream $_test-error-buffered-file->buffer)
12577     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12578     68/push 0/imm32
12579     68/push 0/imm32
12580     89/<- %edx 4/r32/esp
12581     (tailor-exit-descriptor %edx 0x10)
12582     #
12583     (write _test-input-stream "fn foo {\n")
12584     (write _test-input-stream "  var a/ebx: (addr array handle boolean) <- copy 0\n")
12585     (write _test-input-stream "  var o/edi: (addr handle int) <- length a\n")
12586     (write _test-input-stream "}\n")
12587     # convert
12588     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12589     # registers except esp clobbered at this point
12590     # restore ed
12591     89/<- %edx 4/r32/esp
12592     (flush _test-output-buffered-file)
12593     (flush _test-error-buffered-file)
12594 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
12600     # check output
12601     (check-stream-equal _test-output-stream  ""  "F - test-length-with-wrong-output-compound-type: output should be empty")
12602     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt length: output 'o' does not have the right type"  "F - test-length-with-wrong-output-compound-type: error message")
12603     # check that stop(1) was called
12604     (check-ints-equal *(edx+4) 2 "F - test-length-with-wrong-output-compound-type: exit status")
12605     # don't restore from ebp
12606     81 0/subop/add %esp 8/imm32
12607     # . epilogue
12608     5d/pop-to-ebp
12609     c3/return
12610 
12611 test-length-with-no-inouts:
12612     # . prologue
12613     55/push-ebp
12614     89/<- %ebp 4/r32/esp
12615     # setup
12616     (clear-stream _test-input-stream)
12617     (clear-stream $_test-input-buffered-file->buffer)
12618     (clear-stream _test-output-stream)
12619     (clear-stream $_test-output-buffered-file->buffer)
12620     (clear-stream _test-error-stream)
12621     (clear-stream $_test-error-buffered-file->buffer)
12622     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12623     68/push 0/imm32
12624     68/push 0/imm32
12625     89/<- %edx 4/r32/esp
12626     (tailor-exit-descriptor %edx 0x10)
12627     #
12628     (write _test-input-stream "fn foo {\n")
12629     (write _test-input-stream "  var c/ecx: int <- length\n")
12630     (write _test-input-stream "}\n")
12631     # convert
12632     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12633     # registers except esp clobbered at this point
12634     # restore ed
12635     89/<- %edx 4/r32/esp
12636     (flush _test-output-buffered-file)
12637     (flush _test-error-buffered-file)
12638 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
12644     # check output
12645     (check-stream-equal _test-output-stream  ""  "F - test-length-with-no-inouts: output should be empty")
12646     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt length: too few inouts (1 required)"  "F - test-length-with-no-inouts: error message")
12647     # check that stop(1) was called
12648     (check-ints-equal *(edx+4) 2 "F - test-length-with-no-inouts: exit status")
12649     # don't restore from ebp
12650     81 0/subop/add %esp 8/imm32
12651     # . epilogue
12652     5d/pop-to-ebp
12653     c3/return
12654 
12655 test-length-with-too-many-inouts:
12656     # . prologue
12657     55/push-ebp
12658     89/<- %ebp 4/r32/esp
12659     # setup
12660     (clear-stream _test-input-stream)
12661     (clear-stream $_test-input-buffered-file->buffer)
12662     (clear-stream _test-output-stream)
12663     (clear-stream $_test-output-buffered-file->buffer)
12664     (clear-stream _test-error-stream)
12665     (clear-stream $_test-error-buffered-file->buffer)
12666     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12667     68/push 0/imm32
12668     68/push 0/imm32
12669     89/<- %edx 4/r32/esp
12670     (tailor-exit-descriptor %edx 0x10)
12671     #
12672     (write _test-input-stream "fn foo {\n")
12673     (write _test-input-stream "  var a: (array int 3)\n")
12674     (write _test-input-stream "  var c/ecx: int <- length a, 0, 0\n")
12675     (write _test-input-stream "}\n")
12676     # convert
12677     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12678     # registers except esp clobbered at this point
12679     # restore ed
12680     89/<- %edx 4/r32/esp
12681     (flush _test-output-buffered-file)
12682     (flush _test-error-buffered-file)
12683 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
12689     # check output
12690     (check-stream-equal _test-output-stream  ""  "F - test-length-with-too-many-inouts: output should be empty")
12691     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt length: too many inouts (1 required)"  "F - test-length-with-too-many-inouts: error message")
12692     # check that stop(1) was called
12693     (check-ints-equal *(edx+4) 2 "F - test-length-with-too-many-inouts: exit status")
12694     # don't restore from ebp
12695     81 0/subop/add %esp 8/imm32
12696     # . epilogue
12697     5d/pop-to-ebp
12698     c3/return
12699 
12700 test-length-with-no-output:
12701     # . prologue
12702     55/push-ebp
12703     89/<- %ebp 4/r32/esp
12704     # setup
12705     (clear-stream _test-input-stream)
12706     (clear-stream $_test-input-buffered-file->buffer)
12707     (clear-stream _test-output-stream)
12708     (clear-stream $_test-output-buffered-file->buffer)
12709     (clear-stream _test-error-stream)
12710     (clear-stream $_test-error-buffered-file->buffer)
12711     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12712     68/push 0/imm32
12713     68/push 0/imm32
12714     89/<- %edx 4/r32/esp
12715     (tailor-exit-descriptor %edx 0x10)
12716     #
12717     (write _test-input-stream "fn foo {\n")
12718     (write _test-input-stream "  var a: (array int 3)\n")
12719     (write _test-input-stream "  length a\n")
12720     (write _test-input-stream "}\n")
12721     # convert
12722     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12723     # registers except esp clobbered at this point
12724     # restore ed
12725     89/<- %edx 4/r32/esp
12726     (flush _test-output-buffered-file)
12727     (flush _test-error-buffered-file)
12728 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
12734     # check output
12735     (check-stream-equal _test-output-stream  ""  "F - test-length-with-no-output: output should be empty")
12736     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt length: must have an output"  "F - test-length-with-no-output: error message")
12737     # check that stop(1) was called
12738     (check-ints-equal *(edx+4) 2 "F - test-length-with-no-output: exit status")
12739     # don't restore from ebp
12740     81 0/subop/add %esp 8/imm32
12741     # . epilogue
12742     5d/pop-to-ebp
12743     c3/return
12744 
12745 test-length-with-too-many-outputs:
12746     # . prologue
12747     55/push-ebp
12748     89/<- %ebp 4/r32/esp
12749     # setup
12750     (clear-stream _test-input-stream)
12751     (clear-stream $_test-input-buffered-file->buffer)
12752     (clear-stream _test-output-stream)
12753     (clear-stream $_test-output-buffered-file->buffer)
12754     (clear-stream _test-error-stream)
12755     (clear-stream $_test-error-buffered-file->buffer)
12756     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
12757     68/push 0/imm32
12758     68/push 0/imm32
12759     89/<- %edx 4/r32/esp
12760     (tailor-exit-descriptor %edx 0x10)
12761     #
12762     (write _test-input-stream "fn foo {\n")
12763     (write _test-input-stream "  var a: (array int 3)\n")
12764     (write _test-input-stream "  var b/eax: int <- copy 0\n")
12765     (write _test-input-stream "  var c/ecx: int <- copy 0\n")
12766     (write _test-input-stream "  b, c <- length a\n")
12767     (write _test-input-stream "}\n")
12768     # convert
12769     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
12770     # registers except esp clobbered at this point
12771     # restore ed
12772     89/<- %edx 4/r32/esp
12773     (flush _test-output-buffered-file)
12774     (flush _test-error-buffered-file)
12775 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
12781     # check output
12782     (check-stream-equal _test-output-stream  ""  "F - test-length-with-too-many-outputs: output should be empty")
12783     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt length: too many outputs (1 required)"  "F - test-length-with-too-many-outputs: error message")
12784     # check that stop(1) was called
12785     (check-ints-equal *(edx+4) 2 "F - test-length-with-too-many-outputs: exit status")
12786     # don't restore from ebp
12787     81 0/subop/add %esp 8/imm32
12788     # . epilogue
12789     5d/pop-to-ebp
12790     c3/return
12791 
12792 test-convert-function-with-return-register-and-local:
12793     # . prologue
12794     55/push-ebp
12795     89/<- %ebp 4/r32/esp
12796     # setup
12797     (clear-stream _test-input-stream)
12798     (clear-stream $_test-input-buffered-file->buffer)
12799     (clear-stream _test-output-stream)
12800     (clear-stream $_test-output-buffered-file->buffer)
12801     #
12802     (write _test-input-stream "fn foo -> _/eax: int {\n")
12803     (write _test-input-stream "  var y/eax: int <- copy 3\n")
12804     (write _test-input-stream "  var z/ecx: int <- copy 4\n")
12805     (write _test-input-stream "  return y\n")
12806     (write _test-input-stream "}\n")
12807     # convert
12808     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
12809     (flush _test-output-buffered-file)
12810 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
12816     # check output
12817     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-register-and-local/0")
12818     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-register-and-local/1")
12819     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-register-and-local/2")
12820     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-register-and-local/3")
12821     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-register-and-local/4")
12822     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-register-and-local/5")
12823     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-with-return-register-and-local/6")
12824     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 3/imm32"  "F - test-convert-function-with-return-register-and-local/7")
12825     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-return-register-and-local/8")
12826     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 4/imm32"  "F - test-convert-function-with-return-register-and-local/9")
12827     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32" "F - test-convert-function-with-return-register-and-local/10")
12828     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-function-with-return-register-and-local/11")
12829     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-with-return-register-and-local/12")
12830     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-register-and-local/13")
12831     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-register-and-local/14")
12832     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-register-and-local/15")
12833     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-register-and-local/16")
12834     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-register-and-local/17")
12835     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-register-and-local/18")
12836     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-register-and-local/19")
12837     # . epilogue
12838     89/<- %esp 5/r32/ebp
12839     5d/pop-to-ebp
12840     c3/return
12841 
12842 test-convert-function-with-return-register-and-local-2:
12843     # . prologue
12844     55/push-ebp
12845     89/<- %ebp 4/r32/esp
12846     # setup
12847     (clear-stream _test-input-stream)
12848     (clear-stream $_test-input-buffered-file->buffer)
12849     (clear-stream _test-output-stream)
12850     (clear-stream $_test-output-buffered-file->buffer)
12851     #
12852     (write _test-input-stream "fn foo -> _/eax: int {\n")
12853     (write _test-input-stream "  var y/eax: int <- copy 3\n")
12854     (write _test-input-stream "  var z/ecx: int <- copy 4\n")
12855     (write _test-input-stream "  return z\n")
12856     (write _test-input-stream "}\n")
12857     # convert
12858     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
12859     (flush _test-output-buffered-file)
12860 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
12866     # check output
12867     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-register-and-local-2/0")
12868     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-register-and-local-2/1")
12869     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-register-and-local-2/2")
12870     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-register-and-local-2/3")
12871     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-register-and-local-2/4")
12872     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-register-and-local-2/5")
12873     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-with-return-register-and-local-2/6")
12874     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 3/imm32"  "F - test-convert-function-with-return-register-and-local-2/7")
12875     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-return-register-and-local-2/8")
12876     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 4/imm32"  "F - test-convert-function-with-return-register-and-local-2/9")
12877     (check-next-stream-line-equal _test-output-stream "    8b/-> %ecx 0x00000000/r32" "F - test-convert-function-with-return-register-and-local-2/10")
12878     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-function-with-return-register-and-local-2/11")
12879     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-with-return-register-and-local-2/12")
12880     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-register-and-local-2/13")
12881     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-register-and-local-2/14")
12882     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-register-and-local-2/15")
12883     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-register-and-local-2/16")
12884     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-register-and-local-2/17")
12885     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-register-and-local-2/18")
12886     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-register-and-local-2/19")
12887     # . epilogue
12888     89/<- %esp 5/r32/ebp
12889     5d/pop-to-ebp
12890     c3/return
12891 
12892 test-convert-function-with-return-float-register-and-local:
12893     # . prologue
12894     55/push-ebp
12895     89/<- %ebp 4/r32/esp
12896     # setup
12897     (clear-stream _test-input-stream)
12898     (clear-stream $_test-input-buffered-file->buffer)
12899     (clear-stream _test-output-stream)
12900     (clear-stream $_test-output-buffered-file->buffer)
12901     #
12902     (write _test-input-stream "fn foo -> _/xmm1: float {\n")
12903     (write _test-input-stream "  var y/eax: int <- copy 3\n")
12904     (write _test-input-stream "  var g/xmm0: float <- convert y\n")
12905     (write _test-input-stream "  var h/xmm1: float <- convert y\n")
12906     (write _test-input-stream "  return g\n")
12907     (write _test-input-stream "}\n")
12908     # convert
12909     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
12910     (flush _test-output-buffered-file)
12911 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
12917     # check output
12918     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-float-register-and-local/0")
12919     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-float-register-and-local/1")
12920     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-float-register-and-local/2")
12921     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-float-register-and-local/3")
12922     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-float-register-and-local/4")
12923     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-float-register-and-local/5")
12924     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-with-return-float-register-and-local/6")  # var y
12925     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 3/imm32"  "F - test-convert-function-with-return-float-register-and-local/7")
12926     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"  "F - test-convert-function-with-return-float-register-and-local/8")  # var g
12927     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 0/x32"  "F - test-convert-function-with-return-float-register-and-local/9")
12928     (check-next-stream-line-equal _test-output-stream "    f3 0f 2a/convert-to-float %eax 0x00000000/x32"  "F - test-convert-function-with-return-float-register-and-local/10")
12929     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"  "F - test-convert-function-with-return-float-register-and-local/11")  # var h
12930     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"  "F - test-convert-function-with-return-float-register-and-local/12")
12931     (check-next-stream-line-equal _test-output-stream "    f3 0f 2a/convert-to-float %eax 0x00000001/x32"  "F - test-convert-function-with-return-float-register-and-local/13")
12932     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> %xmm0 0x00000001/x32"  "F - test-convert-function-with-return-float-register-and-local/14")  # return g
12933     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-floating-point-dereferenced/15")  # reclaim h
12934     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 0/x32"  "F - test-convert-floating-point-dereferenced/16")  # reclaim g
12935     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-floating-point-dereferenced/17")
12936     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"         "F - test-convert-function-with-return-float-register-and-local/18")  # reclaim y
12937     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-float-register-and-local/19")
12938     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-float-register-and-local/20")
12939     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-float-register-and-local/21")
12940     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-float-register-and-local/22")
12941     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-float-register-and-local/23")
12942     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-float-register-and-local/24")
12943     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-float-register-and-local/25")
12944     # . epilogue
12945     89/<- %esp 5/r32/ebp
12946     5d/pop-to-ebp
12947     c3/return
12948 
12949 test-convert-function-with-return-and-local-vars:
12950     # . prologue
12951     55/push-ebp
12952     89/<- %ebp 4/r32/esp
12953     # setup
12954     (clear-stream _test-input-stream)
12955     (clear-stream $_test-input-buffered-file->buffer)
12956     (clear-stream _test-output-stream)
12957     (clear-stream $_test-output-buffered-file->buffer)
12958     #
12959     (write _test-input-stream "fn foo -> _/eax: int {\n")
12960     (write _test-input-stream "  {\n")
12961     (write _test-input-stream "    var x: int\n")
12962     (write _test-input-stream "    {\n")
12963     (write _test-input-stream "      var y: int\n")
12964     (write _test-input-stream "      return y\n")
12965     (write _test-input-stream "      increment x\n")
12966     (write _test-input-stream "    }\n")
12967     (write _test-input-stream "  }\n")
12968     (write _test-input-stream "  return 0\n")
12969     (write _test-input-stream "}\n")
12970     # convert
12971     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
12972     (flush _test-output-buffered-file)
12973 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
12979     # check output
12980     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-and-local-vars/0")
12981     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-and-local-vars/1")
12982     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-and-local-vars/2")
12983     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-and-local-vars/3")
12984     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-and-local-vars/4")
12985     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-and-local-vars/5")
12986     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-return-and-local-vars/6")
12987     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-return-and-local-vars/7")
12988     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-return-and-local-vars/8")  # var x
12989     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-return-and-local-vars/9")
12990     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-return-and-local-vars/10")
12991     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-return-and-local-vars/11")  # var y
12992     (check-next-stream-line-equal _test-output-stream "        8b/-> *(ebp+0xfffffff8) 0x00000000/r32" "F - test-convert-function-with-return-and-local-vars/12")
12993     (check-next-stream-line-equal _test-output-stream "        81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-return-and-local-vars/13")
12994     (check-next-stream-line-equal _test-output-stream "        81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-return-and-local-vars/14")
12995     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-and-local-vars/15")
12996     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-return-and-local-vars/16")
12997     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-return-and-local-vars/17")
12998     (check-next-stream-line-equal _test-output-stream "      81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-return-and-local-vars/18")
12999     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-return-and-local-vars/19")
13000     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-return-and-local-vars/20")
13001     (check-next-stream-line-equal _test-output-stream "    c7 0/subop/copy %eax 0/imm32"  "F - test-convert-function-with-return-and-local-vars/21")
13002     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-and-local-vars/21")
13003     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-and-local-vars/21")
13004     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-and-local-vars/22")
13005     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-and-local-vars/23")
13006     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-and-local-vars/24")
13007     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-and-local-vars/25")
13008     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-and-local-vars/26")
13009     # . epilogue
13010     89/<- %esp 5/r32/ebp
13011     5d/pop-to-ebp
13012     c3/return
13013 
13014 test-copy-object-with-no-inout:
13015     # . prologue
13016     55/push-ebp
13017     89/<- %ebp 4/r32/esp
13018     # setup
13019     (clear-stream _test-input-stream)
13020     (clear-stream $_test-input-buffered-file->buffer)
13021     (clear-stream _test-output-stream)
13022     (clear-stream $_test-output-buffered-file->buffer)
13023     (clear-stream _test-error-stream)
13024     (clear-stream $_test-error-buffered-file->buffer)
13025     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13026     68/push 0/imm32
13027     68/push 0/imm32
13028     89/<- %edx 4/r32/esp
13029     (tailor-exit-descriptor %edx 0x10)
13030     #
13031     (write _test-input-stream "fn foo {\n")
13032     (write _test-input-stream "  copy-object\n")
13033     (write _test-input-stream "}\n")
13034     # convert
13035     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13036     # registers except esp clobbered at this point
13037     # restore ed
13038     89/<- %edx 4/r32/esp
13039     (flush _test-output-buffered-file)
13040     (flush _test-error-buffered-file)
13041 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
13047     # check output
13048     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-with-no-inout: output should be empty")
13049     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-object' must have two inouts"  "F - test-copy-object-with-no-inout: error message")
13050     # check that stop(1) was called
13051     (check-ints-equal *(edx+4) 2 "F - test-copy-object-with-no-inout: exit status")
13052     # don't restore from ebp
13053     81 0/subop/add %esp 8/imm32
13054     # . epilogue
13055     5d/pop-to-ebp
13056     c3/return
13057 
13058 test-copy-object-with-no-input:
13059     # . prologue
13060     55/push-ebp
13061     89/<- %ebp 4/r32/esp
13062     # setup
13063     (clear-stream _test-input-stream)
13064     (clear-stream $_test-input-buffered-file->buffer)
13065     (clear-stream _test-output-stream)
13066     (clear-stream $_test-output-buffered-file->buffer)
13067     (clear-stream _test-error-stream)
13068     (clear-stream $_test-error-buffered-file->buffer)
13069     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13070     68/push 0/imm32
13071     68/push 0/imm32
13072     89/<- %edx 4/r32/esp
13073     (tailor-exit-descriptor %edx 0x10)
13074     #
13075     (write _test-input-stream "fn foo {\n")
13076     (write _test-input-stream "  var x: (addr int)\n")
13077     (write _test-input-stream "  copy-object x\n")
13078     (write _test-input-stream "}\n")
13079     # convert
13080     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13081     # registers except esp clobbered at this point
13082     # restore ed
13083     89/<- %edx 4/r32/esp
13084     (flush _test-output-buffered-file)
13085     (flush _test-error-buffered-file)
13086 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
13092     # check output
13093     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-with-no-input: output should be empty")
13094     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-object' must have two inouts"  "F - test-copy-object-with-no-input: error message")
13095     # check that stop(1) was called
13096     (check-ints-equal *(edx+4) 2 "F - test-copy-object-with-no-input: exit status")
13097     # don't restore from ebp
13098     81 0/subop/add %esp 8/imm32
13099     # . epilogue
13100     5d/pop-to-ebp
13101     c3/return
13102 
13103 test-copy-object-with-too-many-inouts:
13104     # . prologue
13105     55/push-ebp
13106     89/<- %ebp 4/r32/esp
13107     # setup
13108     (clear-stream _test-input-stream)
13109     (clear-stream $_test-input-buffered-file->buffer)
13110     (clear-stream _test-output-stream)
13111     (clear-stream $_test-output-buffered-file->buffer)
13112     (clear-stream _test-error-stream)
13113     (clear-stream $_test-error-buffered-file->buffer)
13114     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13115     68/push 0/imm32
13116     68/push 0/imm32
13117     89/<- %edx 4/r32/esp
13118     (tailor-exit-descriptor %edx 0x10)
13119     #
13120     (write _test-input-stream "fn foo {\n")
13121     (write _test-input-stream "  var x: (addr boolean)\n")
13122     (write _test-input-stream "  copy-object x, x, x\n")
13123     (write _test-input-stream "}\n")
13124     # convert
13125     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13126     # registers except esp clobbered at this point
13127     # restore ed
13128     89/<- %edx 4/r32/esp
13129     (flush _test-output-buffered-file)
13130     (flush _test-error-buffered-file)
13131 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
13137     # check output
13138     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-with-too-many-inouts: output should be empty")
13139     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-object' must have two inouts"  "F - test-copy-object-with-too-many-inouts: error message")
13140     # check that stop(1) was called
13141     (check-ints-equal *(edx+4) 2 "F - test-copy-object-with-too-many-inouts: exit status")
13142     # don't restore from ebp
13143     81 0/subop/add %esp 8/imm32
13144     # . epilogue
13145     5d/pop-to-ebp
13146     c3/return
13147 
13148 test-copy-object-with-output:
13149     # . prologue
13150     55/push-ebp
13151     89/<- %ebp 4/r32/esp
13152     # setup
13153     (clear-stream _test-input-stream)
13154     (clear-stream $_test-input-buffered-file->buffer)
13155     (clear-stream _test-output-stream)
13156     (clear-stream $_test-output-buffered-file->buffer)
13157     (clear-stream _test-error-stream)
13158     (clear-stream $_test-error-buffered-file->buffer)
13159     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13160     68/push 0/imm32
13161     68/push 0/imm32
13162     89/<- %edx 4/r32/esp
13163     (tailor-exit-descriptor %edx 0x10)
13164     #
13165     (write _test-input-stream "fn foo {\n")
13166     (write _test-input-stream "  var x/eax: (addr boolean) <- copy 0\n")
13167     (write _test-input-stream "  var y/ecx: (addr boolean) <- copy 0\n")
13168     (write _test-input-stream "  x <- copy-object x, y\n")
13169     (write _test-input-stream "}\n")
13170     # convert
13171     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13172     # registers except esp clobbered at this point
13173     # restore ed
13174     89/<- %edx 4/r32/esp
13175     (flush _test-output-buffered-file)
13176     (flush _test-error-buffered-file)
13177 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
13183     # check output
13184     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-with-output: output should be empty")
13185     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-object' must not have any outputs"  "F - test-copy-object-with-output: error message")
13186     # check that stop(1) was called
13187     (check-ints-equal *(edx+4) 2 "F - test-copy-object-with-output: exit status")
13188     # don't restore from ebp
13189     81 0/subop/add %esp 8/imm32
13190     # . epilogue
13191     5d/pop-to-ebp
13192     c3/return
13193 
13194 test-copy-object-deref-address:
13195     # . prologue
13196     55/push-ebp
13197     89/<- %ebp 4/r32/esp
13198     # setup
13199     (clear-stream _test-input-stream)
13200     (clear-stream $_test-input-buffered-file->buffer)
13201     (clear-stream _test-output-stream)
13202     (clear-stream $_test-output-buffered-file->buffer)
13203     #
13204     (write _test-input-stream "fn foo {\n")
13205     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
13206     (write _test-input-stream "  var y/ecx: (addr addr int) <- copy 0\n")
13207     (write _test-input-stream "  copy-object *y, x\n")
13208     (write _test-input-stream "}\n")
13209     # convert
13210     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
13211     (flush _test-output-buffered-file)
13212 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
13218     # not bothering checking output
13219     (check-next-stream-line-equal _test-error-stream  ""  "F - test-copy-object-deref-address: error message")
13220     # . epilogue
13221     5d/pop-to-ebp
13222     c3/return
13223 
13224 test-copy-object-non-addr:
13225     # . prologue
13226     55/push-ebp
13227     89/<- %ebp 4/r32/esp
13228     # setup
13229     (clear-stream _test-input-stream)
13230     (clear-stream $_test-input-buffered-file->buffer)
13231     (clear-stream _test-output-stream)
13232     (clear-stream $_test-output-buffered-file->buffer)
13233     (clear-stream _test-error-stream)
13234     (clear-stream $_test-error-buffered-file->buffer)
13235     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13236     68/push 0/imm32
13237     68/push 0/imm32
13238     89/<- %edx 4/r32/esp
13239     (tailor-exit-descriptor %edx 0x10)
13240     #
13241     (write _test-input-stream "fn foo {\n")
13242     (write _test-input-stream "  var x: int\n")
13243     (write _test-input-stream "  var y: int\n")
13244     (write _test-input-stream "  copy-object y, x\n")
13245     (write _test-input-stream "}\n")
13246     # convert
13247     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13248     # registers except esp clobbered at this point
13249     # restore ed
13250     89/<- %edx 4/r32/esp
13251     (flush _test-output-buffered-file)
13252     (flush _test-error-buffered-file)
13253 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
13259     # check output
13260     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-non-addr: output should be empty")
13261     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-object: two inouts with identical addr types expected"  "F - test-copy-object-non-addr: error message")
13262     # check that stop(1) was called
13263     (check-ints-equal *(edx+4) 2 "F - test-copy-object-non-addr: exit status")
13264     # don't restore from ebp
13265     81 0/subop/add %esp 8/imm32
13266     # . epilogue
13267     5d/pop-to-ebp
13268     c3/return
13269 
13270 test-copy-object-non-equal:
13271     # . prologue
13272     55/push-ebp
13273     89/<- %ebp 4/r32/esp
13274     # setup
13275     (clear-stream _test-input-stream)
13276     (clear-stream $_test-input-buffered-file->buffer)
13277     (clear-stream _test-output-stream)
13278     (clear-stream $_test-output-buffered-file->buffer)
13279     (clear-stream _test-error-stream)
13280     (clear-stream $_test-error-buffered-file->buffer)
13281     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13282     68/push 0/imm32
13283     68/push 0/imm32
13284     89/<- %edx 4/r32/esp
13285     (tailor-exit-descriptor %edx 0x10)
13286     #
13287     (write _test-input-stream "fn foo {\n")
13288     (write _test-input-stream "  var x: (addr int)\n")
13289     (write _test-input-stream "  var y: (addr boolean)\n")
13290     (write _test-input-stream "  copy-object y, x\n")
13291     (write _test-input-stream "}\n")
13292     # convert
13293     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13294     # registers except esp clobbered at this point
13295     # restore ed
13296     89/<- %edx 4/r32/esp
13297     (flush _test-output-buffered-file)
13298     (flush _test-error-buffered-file)
13299 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
13305     # check output
13306     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-non-equal: output should be empty")
13307     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-object: two inouts with identical addr types expected"  "F - test-copy-object-non-equal: error message")
13308     # check that stop(1) was called
13309     (check-ints-equal *(edx+4) 2 "F - test-copy-object-non-equal: exit status")
13310     # don't restore from ebp
13311     81 0/subop/add %esp 8/imm32
13312     # . epilogue
13313     5d/pop-to-ebp
13314     c3/return
13315 
13316 test-allocate-with-no-inout:
13317     # . prologue
13318     55/push-ebp
13319     89/<- %ebp 4/r32/esp
13320     # setup
13321     (clear-stream _test-input-stream)
13322     (clear-stream $_test-input-buffered-file->buffer)
13323     (clear-stream _test-output-stream)
13324     (clear-stream $_test-output-buffered-file->buffer)
13325     (clear-stream _test-error-stream)
13326     (clear-stream $_test-error-buffered-file->buffer)
13327     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13328     68/push 0/imm32
13329     68/push 0/imm32
13330     89/<- %edx 4/r32/esp
13331     (tailor-exit-descriptor %edx 0x10)
13332     #
13333     (write _test-input-stream "fn foo {\n")
13334     (write _test-input-stream "  allocate\n")
13335     (write _test-input-stream "}\n")
13336     # convert
13337     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13338     # registers except esp clobbered at this point
13339     # restore ed
13340     89/<- %edx 4/r32/esp
13341     (flush _test-output-buffered-file)
13342     (flush _test-error-buffered-file)
13343 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
13349     # check output
13350     (check-stream-equal _test-output-stream  ""  "F - test-allocate-with-no-inout: output should be empty")
13351     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'allocate' must have a single inout"  "F - test-allocate-with-no-inout: error message")
13352     # check that stop(1) was called
13353     (check-ints-equal *(edx+4) 2 "F - test-allocate-with-no-inout: exit status")
13354     # don't restore from ebp
13355     81 0/subop/add %esp 8/imm32
13356     # . epilogue
13357     5d/pop-to-ebp
13358     c3/return
13359 
13360 test-allocate-with-too-many-inouts:
13361     # . prologue
13362     55/push-ebp
13363     89/<- %ebp 4/r32/esp
13364     # setup
13365     (clear-stream _test-input-stream)
13366     (clear-stream $_test-input-buffered-file->buffer)
13367     (clear-stream _test-output-stream)
13368     (clear-stream $_test-output-buffered-file->buffer)
13369     (clear-stream _test-error-stream)
13370     (clear-stream $_test-error-buffered-file->buffer)
13371     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13372     68/push 0/imm32
13373     68/push 0/imm32
13374     89/<- %edx 4/r32/esp
13375     (tailor-exit-descriptor %edx 0x10)
13376     #
13377     (write _test-input-stream "fn foo {\n")
13378     (write _test-input-stream "  var x: (addr handle int)\n")
13379     (write _test-input-stream "  allocate x, 0\n")
13380     (write _test-input-stream "}\n")
13381     # convert
13382     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13383     # registers except esp clobbered at this point
13384     # restore ed
13385     89/<- %edx 4/r32/esp
13386     (flush _test-output-buffered-file)
13387     (flush _test-error-buffered-file)
13388 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
13394     # check output
13395     (check-stream-equal _test-output-stream  ""  "F - test-allocate-with-too-many-inouts: output should be empty")
13396     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'allocate' must have a single inout"  "F - test-allocate-with-too-many-inouts: error message")
13397     # check that stop(1) was called
13398     (check-ints-equal *(edx+4) 2 "F - test-allocate-with-too-many-inouts: exit status")
13399     # don't restore from ebp
13400     81 0/subop/add %esp 8/imm32
13401     # . epilogue
13402     5d/pop-to-ebp
13403     c3/return
13404 
13405 test-allocate-with-output:
13406     # . prologue
13407     55/push-ebp
13408     89/<- %ebp 4/r32/esp
13409     # setup
13410     (clear-stream _test-input-stream)
13411     (clear-stream $_test-input-buffered-file->buffer)
13412     (clear-stream _test-output-stream)
13413     (clear-stream $_test-output-buffered-file->buffer)
13414     (clear-stream _test-error-stream)
13415     (clear-stream $_test-error-buffered-file->buffer)
13416     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13417     68/push 0/imm32
13418     68/push 0/imm32
13419     89/<- %edx 4/r32/esp
13420     (tailor-exit-descriptor %edx 0x10)
13421     #
13422     (write _test-input-stream "fn foo {\n")
13423     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
13424     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
13425     (write _test-input-stream "  x <- allocate y\n")
13426     (write _test-input-stream "}\n")
13427     # convert
13428     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13429     # registers except esp clobbered at this point
13430     # restore ed
13431     89/<- %edx 4/r32/esp
13432     (flush _test-output-buffered-file)
13433     (flush _test-error-buffered-file)
13434 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
13440     # check output
13441     (check-stream-equal _test-output-stream  ""  "F - test-allocate-with-output: output should be empty")
13442     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'allocate' must not have any outputs"  "F - test-allocate-with-output: error message")
13443     # check that stop(1) was called
13444     (check-ints-equal *(edx+4) 2 "F - test-allocate-with-output: exit status")
13445     # don't restore from ebp
13446     81 0/subop/add %esp 8/imm32
13447     # . epilogue
13448     5d/pop-to-ebp
13449     c3/return
13450 
13451 test-allocate-non-addr:
13452     # . prologue
13453     55/push-ebp
13454     89/<- %ebp 4/r32/esp
13455     # setup
13456     (clear-stream _test-input-stream)
13457     (clear-stream $_test-input-buffered-file->buffer)
13458     (clear-stream _test-output-stream)
13459     (clear-stream $_test-output-buffered-file->buffer)
13460     (clear-stream _test-error-stream)
13461     (clear-stream $_test-error-buffered-file->buffer)
13462     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13463     68/push 0/imm32
13464     68/push 0/imm32
13465     89/<- %edx 4/r32/esp
13466     (tailor-exit-descriptor %edx 0x10)
13467     #
13468     (write _test-input-stream "fn foo {\n")
13469     (write _test-input-stream "  var y: (handle int)\n")
13470     (write _test-input-stream "  allocate y\n")
13471     (write _test-input-stream "}\n")
13472     # convert
13473     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13474     # registers except esp clobbered at this point
13475     # restore ed
13476     89/<- %edx 4/r32/esp
13477     (flush _test-output-buffered-file)
13478     (flush _test-error-buffered-file)
13479 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
13485     # check output
13486     (check-stream-equal _test-output-stream  ""  "F - test-allocate-non-addr: output must be empty")
13487     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt allocate: inout 'y' must have type (addr handle ...)"  "F - test-allocate-non-addr: error message")
13488     # check that stop(1) was called
13489     (check-ints-equal *(edx+4) 2 "F - test-allocate-non-addr: exit status")
13490     # don't restore from ebp
13491     81 0/subop/add %esp 8/imm32
13492     # . epilogue
13493     5d/pop-to-ebp
13494     c3/return
13495 
13496 test-allocate-non-addr-handle:
13497     # . prologue
13498     55/push-ebp
13499     89/<- %ebp 4/r32/esp
13500     # setup
13501     (clear-stream _test-input-stream)
13502     (clear-stream $_test-input-buffered-file->buffer)
13503     (clear-stream _test-output-stream)
13504     (clear-stream $_test-output-buffered-file->buffer)
13505     (clear-stream _test-error-stream)
13506     (clear-stream $_test-error-buffered-file->buffer)
13507     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13508     68/push 0/imm32
13509     68/push 0/imm32
13510     89/<- %edx 4/r32/esp
13511     (tailor-exit-descriptor %edx 0x10)
13512     #
13513     (write _test-input-stream "fn foo {\n")
13514     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
13515     (write _test-input-stream "  allocate y\n")
13516     (write _test-input-stream "}\n")
13517     # convert
13518     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13519     # registers except esp clobbered at this point
13520     # restore ed
13521     89/<- %edx 4/r32/esp
13522     (flush _test-output-buffered-file)
13523     (flush _test-error-buffered-file)
13524 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
13530     # check output
13531     (check-stream-equal _test-output-stream  ""  "F - test-allocate-non-addr-handle: output should be empty")
13532     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt allocate: inout 'y' must have type (addr handle ...)"  "F - test-allocate-non-addr-handle: error message")
13533     # check that stop(1) was called
13534     (check-ints-equal *(edx+4) 2 "F - test-allocate-non-addr-handle: exit status")
13535     # don't restore from ebp
13536     81 0/subop/add %esp 8/imm32
13537     # . epilogue
13538     5d/pop-to-ebp
13539     c3/return
13540 
13541 test-allocate-deref-address:
13542     # . prologue
13543     55/push-ebp
13544     89/<- %ebp 4/r32/esp
13545     # setup
13546     (clear-stream _test-input-stream)
13547     (clear-stream $_test-input-buffered-file->buffer)
13548     (clear-stream _test-output-stream)
13549     (clear-stream $_test-output-buffered-file->buffer)
13550     #
13551     (write _test-input-stream "fn foo {\n")
13552     (write _test-input-stream "  var y/ecx: (addr addr handle int) <- copy 0\n")
13553     (write _test-input-stream "  allocate *y\n")
13554     (write _test-input-stream "}\n")
13555     # convert
13556     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
13557     (flush _test-output-buffered-file)
13558 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
13564     # not bothering checking output
13565     (check-next-stream-line-equal _test-error-stream  ""  "F - test-allocate-deref-address: error message")
13566     # . epilogue
13567     5d/pop-to-ebp
13568     c3/return
13569 
13570 test-populate-with-no-inout:
13571     # . prologue
13572     55/push-ebp
13573     89/<- %ebp 4/r32/esp
13574     # setup
13575     (clear-stream _test-input-stream)
13576     (clear-stream $_test-input-buffered-file->buffer)
13577     (clear-stream _test-output-stream)
13578     (clear-stream $_test-output-buffered-file->buffer)
13579     (clear-stream _test-error-stream)
13580     (clear-stream $_test-error-buffered-file->buffer)
13581     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13582     68/push 0/imm32
13583     68/push 0/imm32
13584     89/<- %edx 4/r32/esp
13585     (tailor-exit-descriptor %edx 0x10)
13586     #
13587     (write _test-input-stream "fn foo {\n")
13588     (write _test-input-stream "  populate\n")
13589     (write _test-input-stream "}\n")
13590     # convert
13591     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13592     # registers except esp clobbered at this point
13593     # restore ed
13594     89/<- %edx 4/r32/esp
13595     (flush _test-output-buffered-file)
13596     (flush _test-error-buffered-file)
13597 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
13603     # check output
13604     (check-stream-equal _test-output-stream  ""  "F - test-populate-with-no-inout: output should be empty")
13605     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'populate' must have two inouts"  "F - test-populate-with-no-inout: error message")
13606     # check that stop(1) was called
13607     (check-ints-equal *(edx+4) 2 "F - test-populate-with-no-inout: exit status")
13608     # don't restore from ebp
13609     81 0/subop/add %esp 8/imm32
13610     # . epilogue
13611     5d/pop-to-ebp
13612     c3/return
13613 
13614 test-populate-with-too-many-inouts:
13615     # . prologue
13616     55/push-ebp
13617     89/<- %ebp 4/r32/esp
13618     # setup
13619     (clear-stream _test-input-stream)
13620     (clear-stream $_test-input-buffered-file->buffer)
13621     (clear-stream _test-output-stream)
13622     (clear-stream $_test-output-buffered-file->buffer)
13623     (clear-stream _test-error-stream)
13624     (clear-stream $_test-error-buffered-file->buffer)
13625     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13626     68/push 0/imm32
13627     68/push 0/imm32
13628     89/<- %edx 4/r32/esp
13629     (tailor-exit-descriptor %edx 0x10)
13630     #
13631     (write _test-input-stream "fn foo {\n")
13632     (write _test-input-stream "  var x: (addr handle int)\n")
13633     (write _test-input-stream "  populate x, 3, 0\n")
13634     (write _test-input-stream "}\n")
13635     # convert
13636     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13637     # registers except esp clobbered at this point
13638     # restore ed
13639     89/<- %edx 4/r32/esp
13640     (flush _test-output-buffered-file)
13641     (flush _test-error-buffered-file)
13642 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
13648     # check output
13649     (check-stream-equal _test-output-stream  ""  "F - test-populate-with-too-many-inouts: output should be empty")
13650     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'populate' must have two inouts"  "F - test-populate-with-too-many-inouts: error message")
13651     # check that stop(1) was called
13652     (check-ints-equal *(edx+4) 2 "F - test-populate-with-too-many-inouts: exit status")
13653     # don't restore from ebp
13654     81 0/subop/add %esp 8/imm32
13655     # . epilogue
13656     5d/pop-to-ebp
13657     c3/return
13658 
13659 test-populate-with-output:
13660     # . prologue
13661     55/push-ebp
13662     89/<- %ebp 4/r32/esp
13663     # setup
13664     (clear-stream _test-input-stream)
13665     (clear-stream $_test-input-buffered-file->buffer)
13666     (clear-stream _test-output-stream)
13667     (clear-stream $_test-output-buffered-file->buffer)
13668     (clear-stream _test-error-stream)
13669     (clear-stream $_test-error-buffered-file->buffer)
13670     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13671     68/push 0/imm32
13672     68/push 0/imm32
13673     89/<- %edx 4/r32/esp
13674     (tailor-exit-descriptor %edx 0x10)
13675     #
13676     (write _test-input-stream "fn foo {\n")
13677     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
13678     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
13679     (write _test-input-stream "  x <- populate y\n")
13680     (write _test-input-stream "}\n")
13681     # convert
13682     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13683     # registers except esp clobbered at this point
13684     # restore ed
13685     89/<- %edx 4/r32/esp
13686     (flush _test-output-buffered-file)
13687     (flush _test-error-buffered-file)
13688 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
13694     # check output
13695     (check-stream-equal _test-output-stream  ""  "F - test-populate-with-output: output should be empty")
13696     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'populate' must not have any outputs"  "F - test-populate-with-output: error message")
13697     # check that stop(1) was called
13698     (check-ints-equal *(edx+4) 2 "F - test-populate-with-output: exit status")
13699     # don't restore from ebp
13700     81 0/subop/add %esp 8/imm32
13701     # . epilogue
13702     5d/pop-to-ebp
13703     c3/return
13704 
13705 test-populate-non-addr:
13706     # . prologue
13707     55/push-ebp
13708     89/<- %ebp 4/r32/esp
13709     # setup
13710     (clear-stream _test-input-stream)
13711     (clear-stream $_test-input-buffered-file->buffer)
13712     (clear-stream _test-output-stream)
13713     (clear-stream $_test-output-buffered-file->buffer)
13714     (clear-stream _test-error-stream)
13715     (clear-stream $_test-error-buffered-file->buffer)
13716     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13717     68/push 0/imm32
13718     68/push 0/imm32
13719     89/<- %edx 4/r32/esp
13720     (tailor-exit-descriptor %edx 0x10)
13721     #
13722     (write _test-input-stream "fn foo {\n")
13723     (write _test-input-stream "  var y: (handle int)\n")
13724     (write _test-input-stream "  populate y, 3\n")
13725     (write _test-input-stream "}\n")
13726     # convert
13727     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13728     # registers except esp clobbered at this point
13729     # restore ed
13730     89/<- %edx 4/r32/esp
13731     (flush _test-output-buffered-file)
13732     (flush _test-error-buffered-file)
13733 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
13739     # check output
13740     (check-stream-equal _test-output-stream  ""  "F - test-populate-non-addr: output must be empty")
13741     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt populate: first inout 'y' must have type (addr handle array ...)"  "F - test-populate-non-addr: error message")
13742     # check that stop(1) was called
13743     (check-ints-equal *(edx+4) 2 "F - test-populate-non-addr: exit status")
13744     # don't restore from ebp
13745     81 0/subop/add %esp 8/imm32
13746     # . epilogue
13747     5d/pop-to-ebp
13748     c3/return
13749 
13750 test-populate-non-addr-handle:
13751     # . prologue
13752     55/push-ebp
13753     89/<- %ebp 4/r32/esp
13754     # setup
13755     (clear-stream _test-input-stream)
13756     (clear-stream $_test-input-buffered-file->buffer)
13757     (clear-stream _test-output-stream)
13758     (clear-stream $_test-output-buffered-file->buffer)
13759     (clear-stream _test-error-stream)
13760     (clear-stream $_test-error-buffered-file->buffer)
13761     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13762     68/push 0/imm32
13763     68/push 0/imm32
13764     89/<- %edx 4/r32/esp
13765     (tailor-exit-descriptor %edx 0x10)
13766     #
13767     (write _test-input-stream "fn foo {\n")
13768     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
13769     (write _test-input-stream "  populate y, 3\n")
13770     (write _test-input-stream "}\n")
13771     # convert
13772     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13773     # registers except esp clobbered at this point
13774     # restore ed
13775     89/<- %edx 4/r32/esp
13776     (flush _test-output-buffered-file)
13777     (flush _test-error-buffered-file)
13778 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
13784     # check output
13785     (check-stream-equal _test-output-stream  ""  "F - test-populate-non-addr-handle: output should be empty")
13786     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt populate: first inout 'y' must have type (addr handle array ...)"  "F - test-populate-non-addr-handle: error message")
13787     # check that stop(1) was called
13788     (check-ints-equal *(edx+4) 2 "F - test-populate-non-addr-handle: exit status")
13789     # don't restore from ebp
13790     81 0/subop/add %esp 8/imm32
13791     # . epilogue
13792     5d/pop-to-ebp
13793     c3/return
13794 
13795 test-populate-non-addr-handle-array:
13796     # . prologue
13797     55/push-ebp
13798     89/<- %ebp 4/r32/esp
13799     # setup
13800     (clear-stream _test-input-stream)
13801     (clear-stream $_test-input-buffered-file->buffer)
13802     (clear-stream _test-output-stream)
13803     (clear-stream $_test-output-buffered-file->buffer)
13804     (clear-stream _test-error-stream)
13805     (clear-stream $_test-error-buffered-file->buffer)
13806     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13807     68/push 0/imm32
13808     68/push 0/imm32
13809     89/<- %edx 4/r32/esp
13810     (tailor-exit-descriptor %edx 0x10)
13811     #
13812     (write _test-input-stream "fn foo {\n")
13813     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
13814     (write _test-input-stream "  populate y, 3\n")
13815     (write _test-input-stream "}\n")
13816     # convert
13817     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13818     # registers except esp clobbered at this point
13819     # restore ed
13820     89/<- %edx 4/r32/esp
13821     (flush _test-output-buffered-file)
13822     (flush _test-error-buffered-file)
13823 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
13829     # check output
13830     (check-stream-equal _test-output-stream  ""  "F - test-populate-non-addr-handle-array: output should be empty")
13831     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt populate: first inout 'y' must have type (addr handle array ...)"  "F - test-populate-non-addr-handle-array: error message")
13832     # check that stop(1) was called
13833     (check-ints-equal *(edx+4) 2 "F - test-populate-non-addr-handle-array: exit status")
13834     # don't restore from ebp
13835     81 0/subop/add %esp 8/imm32
13836     # . epilogue
13837     5d/pop-to-ebp
13838     c3/return
13839 
13840 test-populate-deref-address:
13841     # . prologue
13842     55/push-ebp
13843     89/<- %ebp 4/r32/esp
13844     # setup
13845     (clear-stream _test-input-stream)
13846     (clear-stream $_test-input-buffered-file->buffer)
13847     (clear-stream _test-output-stream)
13848     (clear-stream $_test-output-buffered-file->buffer)
13849     #
13850     (write _test-input-stream "fn foo {\n")
13851     (write _test-input-stream "  var y/ecx: (addr addr handle array int) <- copy 0\n")
13852     (write _test-input-stream "  populate *y, 3\n")
13853     (write _test-input-stream "}\n")
13854     # convert
13855     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
13856     (flush _test-output-buffered-file)
13857 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
13863     # not bothering checking output
13864     (check-next-stream-line-equal _test-error-stream  ""  "F - test-populate-deref-address: error message")
13865     # . epilogue
13866     5d/pop-to-ebp
13867     c3/return
13868 
13869 test-populate-stream-with-no-inout:
13870     # . prologue
13871     55/push-ebp
13872     89/<- %ebp 4/r32/esp
13873     # setup
13874     (clear-stream _test-input-stream)
13875     (clear-stream $_test-input-buffered-file->buffer)
13876     (clear-stream _test-output-stream)
13877     (clear-stream $_test-output-buffered-file->buffer)
13878     (clear-stream _test-error-stream)
13879     (clear-stream $_test-error-buffered-file->buffer)
13880     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13881     68/push 0/imm32
13882     68/push 0/imm32
13883     89/<- %edx 4/r32/esp
13884     (tailor-exit-descriptor %edx 0x10)
13885     #
13886     (write _test-input-stream "fn foo {\n")
13887     (write _test-input-stream "  populate-stream\n")
13888     (write _test-input-stream "}\n")
13889     # convert
13890     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13891     # registers except esp clobbered at this point
13892     # restore ed
13893     89/<- %edx 4/r32/esp
13894     (flush _test-output-buffered-file)
13895     (flush _test-error-buffered-file)
13896 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
13902     # check output
13903     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-with-no-inout: output should be empty")
13904     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'populate-stream' must have two inouts"  "F - test-populate-stream-with-no-inout: error message")
13905     # check that stop(1) was called
13906     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-with-no-inout: exit status")
13907     # don't restore from ebp
13908     81 0/subop/add %esp 8/imm32
13909     # . epilogue
13910     5d/pop-to-ebp
13911     c3/return
13912 
13913 test-populate-stream-with-too-many-inouts:
13914     # . prologue
13915     55/push-ebp
13916     89/<- %ebp 4/r32/esp
13917     # setup
13918     (clear-stream _test-input-stream)
13919     (clear-stream $_test-input-buffered-file->buffer)
13920     (clear-stream _test-output-stream)
13921     (clear-stream $_test-output-buffered-file->buffer)
13922     (clear-stream _test-error-stream)
13923     (clear-stream $_test-error-buffered-file->buffer)
13924     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13925     68/push 0/imm32
13926     68/push 0/imm32
13927     89/<- %edx 4/r32/esp
13928     (tailor-exit-descriptor %edx 0x10)
13929     #
13930     (write _test-input-stream "fn foo {\n")
13931     (write _test-input-stream "  var x: (addr handle int)\n")
13932     (write _test-input-stream "  populate-stream x, 3, 0\n")
13933     (write _test-input-stream "}\n")
13934     # convert
13935     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13936     # registers except esp clobbered at this point
13937     # restore ed
13938     89/<- %edx 4/r32/esp
13939     (flush _test-output-buffered-file)
13940     (flush _test-error-buffered-file)
13941 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
13947     # check output
13948     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-with-too-many-inouts: output should be empty")
13949     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'populate-stream' must have two inouts"  "F - test-populate-stream-with-too-many-inouts: error message")
13950     # check that stop(1) was called
13951     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-with-too-many-inouts: exit status")
13952     # don't restore from ebp
13953     81 0/subop/add %esp 8/imm32
13954     # . epilogue
13955     5d/pop-to-ebp
13956     c3/return
13957 
13958 test-populate-stream-with-output:
13959     # . prologue
13960     55/push-ebp
13961     89/<- %ebp 4/r32/esp
13962     # setup
13963     (clear-stream _test-input-stream)
13964     (clear-stream $_test-input-buffered-file->buffer)
13965     (clear-stream _test-output-stream)
13966     (clear-stream $_test-output-buffered-file->buffer)
13967     (clear-stream _test-error-stream)
13968     (clear-stream $_test-error-buffered-file->buffer)
13969     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
13970     68/push 0/imm32
13971     68/push 0/imm32
13972     89/<- %edx 4/r32/esp
13973     (tailor-exit-descriptor %edx 0x10)
13974     #
13975     (write _test-input-stream "fn foo {\n")
13976     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
13977     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
13978     (write _test-input-stream "  x <- populate-stream y\n")
13979     (write _test-input-stream "}\n")
13980     # convert
13981     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
13982     # registers except esp clobbered at this point
13983     # restore ed
13984     89/<- %edx 4/r32/esp
13985     (flush _test-output-buffered-file)
13986     (flush _test-error-buffered-file)
13987 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
13993     # check output
13994     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-with-output: output should be empty")
13995     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'populate-stream' must not have any outputs"  "F - test-populate-stream-with-output: error message")
13996     # check that stop(1) was called
13997     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-with-output: exit status")
13998     # don't restore from ebp
13999     81 0/subop/add %esp 8/imm32
14000     # . epilogue
14001     5d/pop-to-ebp
14002     c3/return
14003 
14004 test-populate-stream-non-addr:
14005     # . prologue
14006     55/push-ebp
14007     89/<- %ebp 4/r32/esp
14008     # setup
14009     (clear-stream _test-input-stream)
14010     (clear-stream $_test-input-buffered-file->buffer)
14011     (clear-stream _test-output-stream)
14012     (clear-stream $_test-output-buffered-file->buffer)
14013     (clear-stream _test-error-stream)
14014     (clear-stream $_test-error-buffered-file->buffer)
14015     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14016     68/push 0/imm32
14017     68/push 0/imm32
14018     89/<- %edx 4/r32/esp
14019     (tailor-exit-descriptor %edx 0x10)
14020     #
14021     (write _test-input-stream "fn foo {\n")
14022     (write _test-input-stream "  var y: (handle int)\n")
14023     (write _test-input-stream "  populate-stream y, 3\n")
14024     (write _test-input-stream "}\n")
14025     # convert
14026     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14027     # registers except esp clobbered at this point
14028     # restore ed
14029     89/<- %edx 4/r32/esp
14030     (flush _test-output-buffered-file)
14031     (flush _test-error-buffered-file)
14032 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
14038     # check output
14039     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-non-addr: output must be empty")
14040     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt populate-stream: first inout 'y' must have type (addr handle stream ...)"  "F - test-populate-stream-non-addr: error message")
14041     # check that stop(1) was called
14042     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-non-addr: exit status")
14043     # don't restore from ebp
14044     81 0/subop/add %esp 8/imm32
14045     # . epilogue
14046     5d/pop-to-ebp
14047     c3/return
14048 
14049 test-populate-stream-non-addr-handle:
14050     # . prologue
14051     55/push-ebp
14052     89/<- %ebp 4/r32/esp
14053     # setup
14054     (clear-stream _test-input-stream)
14055     (clear-stream $_test-input-buffered-file->buffer)
14056     (clear-stream _test-output-stream)
14057     (clear-stream $_test-output-buffered-file->buffer)
14058     (clear-stream _test-error-stream)
14059     (clear-stream $_test-error-buffered-file->buffer)
14060     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14061     68/push 0/imm32
14062     68/push 0/imm32
14063     89/<- %edx 4/r32/esp
14064     (tailor-exit-descriptor %edx 0x10)
14065     #
14066     (write _test-input-stream "fn foo {\n")
14067     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
14068     (write _test-input-stream "  populate-stream y, 3\n")
14069     (write _test-input-stream "}\n")
14070     # convert
14071     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14072     # registers except esp clobbered at this point
14073     # restore ed
14074     89/<- %edx 4/r32/esp
14075     (flush _test-output-buffered-file)
14076     (flush _test-error-buffered-file)
14077 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
14083     # check output
14084     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-non-addr-handle: output should be empty")
14085     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt populate-stream: first inout 'y' must have type (addr handle stream ...)"  "F - test-populate-stream-non-addr-handle: error message")
14086     # check that stop(1) was called
14087     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-non-addr-handle: exit status")
14088     # don't restore from ebp
14089     81 0/subop/add %esp 8/imm32
14090     # . epilogue
14091     5d/pop-to-ebp
14092     c3/return
14093 
14094 test-populate-stream-non-addr-handle-stream:
14095     # . prologue
14096     55/push-ebp
14097     89/<- %ebp 4/r32/esp
14098     # setup
14099     (clear-stream _test-input-stream)
14100     (clear-stream $_test-input-buffered-file->buffer)
14101     (clear-stream _test-output-stream)
14102     (clear-stream $_test-output-buffered-file->buffer)
14103     (clear-stream _test-error-stream)
14104     (clear-stream $_test-error-buffered-file->buffer)
14105     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
14106     68/push 0/imm32
14107     68/push 0/imm32
14108     89/<- %edx 4/r32/esp
14109     (tailor-exit-descriptor %edx 0x10)
14110     #
14111     (write _test-input-stream "fn foo {\n")
14112     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
14113     (write _test-input-stream "  populate-stream y, 3\n")
14114     (write _test-input-stream "}\n")
14115     # convert
14116     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
14117     # registers except esp clobbered at this point
14118     # restore ed
14119     89/<- %edx 4/r32/esp
14120     (flush _test-output-buffered-file)
14121     (flush _test-error-buffered-file)
14122 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
14128     # check output
14129     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-non-addr-handle-stream: output should be empty")
14130     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt populate-stream: first inout 'y' must have type (addr handle stream ...)"  "F - test-populate-stream-non-addr-handle-stream: error message")
14131     # check that stop(1) was called
14132     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-non-addr-handle-stream: exit status")
14133     # don't restore from ebp
14134     81 0/subop/add %esp 8/imm32
14135     # . epilogue
14136     5d/pop-to-ebp
14137     c3/return
14138 
14139 test-populate-stream-deref-address:
14140     # . prologue
14141     55/push-ebp
14142     89/<- %ebp 4/r32/esp
14143     # setup
14144     (clear-stream _test-input-stream)
14145     (clear-stream $_test-input-buffered-file->buffer)
14146     (clear-stream _test-output-stream)
14147     (clear-stream $_test-output-buffered-file->buffer)
14148     #
14149     (write _test-input-stream "fn foo {\n")
14150     (write _test-input-stream "  var y/ecx: (addr addr handle stream int) <- copy 0\n")
14151     (write _test-input-stream "  populate-stream *y, 3\n")
14152     (write _test-input-stream "}\n")
14153     # convert
14154     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
14155     (flush _test-output-buffered-file)
14156 +--  6 lines: #?     # dump _test-error-stream ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
14162     # not bothering checking output
14163     (check-next-stream-line-equal _test-error-stream  ""  "F - test-populate-stream-deref-address: error message")
14164     # . epilogue
14165     5d/pop-to-ebp
14166     c3/return
14167 
14168 #######################################################
14169 # Parsing
14170 #######################################################
14171 
14172 == data
14173 
14174 # Global state added to each var record when parsing a function
14175 Next-block-index:  # (addr int)
14176     1/imm32
14177 
14178 Curr-block-depth:  # (addr int)
14179     1/imm32
14180 
14181 == code
14182 
14183 parse-mu:  # in: (addr buffered-file), err: (addr buffered-file), ed: (addr exit-descriptor)
14184     # pseudocode
14185     #   var curr-function: (addr handle function) = Program->functions
14186     #   var curr-signature: (addr handle function) = Program->signatures
14187     #   var curr-type: (addr handle typeinfo) = Program->types
14188     #   var line: (stream byte 512)
14189     #   var word-slice: slice
14190     #   while true                                  # line loop
14191     #     clear-stream(line)
14192     #     read-line-buffered(in, line)
14193     #     if (line->write == 0) break               # end of file
14194     #     word-slice = next-mu-token(line)
14195     #     if slice-empty?(word-slice)               # end of line
14196     #       continue
14197     #     else if slice-starts-with?(word-slice, "#")  # comment
14198     #       continue                                # end of line
14199     #     else if slice-equal?(word-slice, "fn")
14200     #       var new-function: (handle function) = allocate(function)
14201     #       var vars: (stack live-var 256)
14202     #       populate-mu-function-header(line, new-function, vars)
14203     #       populate-mu-function-body(in, new-function, vars)
14204     #       assert(vars->top == 0)
14205     #       *curr-function = new-function
14206     #       curr-function = &new-function->next
14207     #     else if slice-equal?(word-slice, "sig")
14208     #       var new-function: (handle function) = allocate(function)
14209     #       populate-mu-function-signature(line, new-function)
14210     #       *curr-signature = new-function
14211     #       curr-signature = &new-function->next
14212     #     else if slice-equal?(word-slice, "type")
14213     #       word-slice = next-mu-token(line)
14214     #       type-id = pos-or-insert-slice(Type-id, word-slice)
14215     #       var new-type: (handle typeinfo) = find-or-create-typeinfo(type-id)
14216     #       assert(next-word(line) == "{")
14217     #       populate-mu-type(in, new-type)
14218     #     else
14219     #       abort()
14220     #
14221     # . prologue
14222     55/push-ebp
14223     89/<- %ebp 4/r32/esp
14224     # var curr-signature: (addr handle function) at *(ebp-4)
14225     68/push _Program-signatures/imm32
14226     # . save registers
14227     50/push-eax
14228     51/push-ecx
14229     52/push-edx
14230     53/push-ebx
14231     56/push-esi
14232     57/push-edi
14233     # var line/ecx: (stream byte 512)
14234     81 5/subop/subtract %esp 0x200/imm32
14235     68/push 0x200/imm32/size
14236     68/push 0/imm32/read
14237     68/push 0/imm32/write
14238     89/<- %ecx 4/r32/esp
14239     # var word-slice/edx: slice
14240     68/push 0/imm32/end
14241     68/push 0/imm32/start
14242     89/<- %edx 4/r32/esp
14243     # var curr-function/edi: (addr handle function)
14244     bf/copy-to-edi _Program-functions/imm32
14245     # var vars/ebx: (stack live-var 256)
14246     81 5/subop/subtract %esp 0xc00/imm32
14247     68/push 0xc00/imm32/size
14248     68/push 0/imm32/top
14249     89/<- %ebx 4/r32/esp
14250     {
14251 $parse-mu:line-loop:
14252       (clear-stream %ecx)
14253       (read-line-buffered *(ebp+8) %ecx)
14254       # if (line->write == 0) break
14255       81 7/subop/compare *ecx 0/imm32
14256       0f 84/jump-if-= break/disp32
14257 +--  6 lines: #?       # dump line ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
14263       (next-mu-token %ecx %edx)
14264       # if slice-empty?(word-slice) continue
14265       (slice-empty? %edx)  # => eax
14266       3d/compare-eax-and 0/imm32/false
14267       0f 85/jump-if-!= loop/disp32
14268       # if (*word-slice->start == "#") continue
14269       # . eax = *word-slice->start
14270       8b/-> *edx 0/r32/eax
14271       8a/copy-byte *eax 0/r32/AL
14272       81 4/subop/and %eax 0xff/imm32
14273       # . if (eax == '#') continue
14274       3d/compare-eax-and 0x23/imm32/hash
14275       0f 84/jump-if-= loop/disp32
14276       # if (slice-equal?(word-slice, "fn")) parse a function
14277       {
14278 $parse-mu:fn:
14279         (slice-equal? %edx "fn")  # => eax
14280         3d/compare-eax-and 0/imm32/false
14281         0f 84/jump-if-= break/disp32
14282         # var new-function/esi: (handle function)
14283         68/push 0/imm32
14284         68/push 0/imm32
14285         89/<- %esi 4/r32/esp
14286         # populate-mu-function(line, in, vars, new-function)
14287         (allocate Heap *Function-size %esi)
14288         # var new-function-addr/eax: (addr function)
14289         (lookup *esi *(esi+4))  # => eax
14290         # initialize vars
14291         (clear-stack %ebx)
14292         #
14293         (populate-mu-function-header %ecx %eax %ebx *(ebp+0xc) *(ebp+0x10))
14294         (populate-mu-function-body *(ebp+8) %eax %ebx *(ebp+0xc) *(ebp+0x10))
14295         # *curr-function = new-function
14296         8b/-> *esi 0/r32/eax
14297         89/<- *edi 0/r32/eax
14298         8b/-> *(esi+4) 0/r32/eax
14299         89/<- *(edi+4) 0/r32/eax
14300         # curr-function = &new-function->next
14301         # . var tmp/eax: (addr function) = lookup(new-function)
14302         (lookup *esi *(esi+4))  # => eax
14303         # . curr-function = &tmp->next
14304         8d/copy-address *(eax+0x20) 7/r32/edi  # Function-next
14305         # reclaim new-function
14306         81 0/subop/add %esp 8/imm32
14307         #
14308         e9/jump $parse-mu:line-loop/disp32
14309       }
14310       # if (slice-equal?(word-slice, "sig")) parse a function signature
14311       # Function signatures are for providing types to SubX functions.
14312       {
14313 $parse-mu:sig:
14314         (slice-equal? %edx "sig")  # => eax
14315         3d/compare-eax-and 0/imm32/false
14316         0f 84/jump-if-= break/disp32
14317         # edi = curr-function
14318         57/push-edi
14319         8b/-> *(ebp-4) 7/r32/edi
14320         # var new-function/esi: (handle function)
14321         68/push 0/imm32
14322         68/push 0/imm32
14323         89/<- %esi 4/r32/esp
14324         # populate-mu-function(line, in, vars, new-function)
14325         (allocate Heap *Function-size %esi)
14326         # var new-function-addr/eax: (addr function)
14327         (lookup *esi *(esi+4))  # => eax
14328         #
14329         (populate-mu-function-signature %ecx %eax *(ebp+0xc) *(ebp+0x10))
14330         # *curr-signature = new-function
14331         8b/-> *esi 0/r32/eax
14332         89/<- *edi 0/r32/eax
14333         8b/-> *(esi+4) 0/r32/eax
14334         89/<- *(edi+4) 0/r32/eax
14335         # curr-signature = &new-function->next
14336         # . var tmp/eax: (addr function) = lookup(new-function)
14337         (lookup *esi *(esi+4))  # => eax
14338         # . curr-function = &tmp->next
14339         8d/copy-address *(eax+0x20) 7/r32/edi  # Function-next
14340         # reclaim new-function
14341         81 0/subop/add %esp 8/imm32
14342         # save curr-function
14343         89/<- *(ebp-4) 7/r32/edi
14344         # restore edi
14345         5f/pop-to-edi
14346         #
14347         e9/jump $parse-mu:line-loop/disp32
14348       }
14349       # if (slice-equal?(word-slice, "type")) parse a type (struct/record) definition
14350       {
14351 $parse-mu:type:
14352         (slice-equal? %edx "type")  # => eax
14353         3d/compare-eax-and 0/imm32
14354         0f 84/jump-if-= break/disp32
14355         (next-mu-token %ecx %edx)
14356         # var type-id/eax: int
14357         (pos-or-insert-slice Type-id %edx)  # => eax
14358         # spill
14359         51/push-ecx
14360         # var new-type/ecx: (handle typeinfo)
14361         68/push 0/imm32
14362         68/push 0/imm32
14363         89/<- %ecx 4/r32/esp
14364         (find-or-create-typeinfo %eax %ecx)
14365         #
14366         (lookup *ecx *(ecx+4))  # => eax
14367         # TODO: ensure that 'line' has nothing else but '{'
14368 #? (dump-typeinfos "=== aaa\n")
14369         (populate-mu-type *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10))  # => eax
14370 #? (dump-typeinfos "=== zzz\n")
14371         # reclaim new-type
14372         81 0/subop/add %esp 8/imm32
14373         # restore
14374         59/pop-to-ecx
14375         e9/jump $parse-mu:line-loop/disp32
14376       }
14377       # otherwise abort
14378       e9/jump $parse-mu:error1/disp32
14379     } # end line loop
14380 $parse-mu:end:
14381     # . reclaim locals
14382     81 0/subop/add %esp 0x20c/imm32  # line
14383     81 0/subop/add %esp 0xc08/imm32  # vars
14384     81 0/subop/add %esp 8/imm32
14385     # . restore registers
14386     5f/pop-to-edi
14387     5e/pop-to-esi
14388     5b/pop-to-ebx
14389     5a/pop-to-edx
14390     59/pop-to-ecx
14391     58/pop-to-eax
14392     # . reclaim local
14393     81 0/subop/add %esp 4/imm32
14394     # . epilogue
14395     89/<- %esp 5/r32/ebp
14396     5d/pop-to-ebp
14397     c3/return
14398 
14399 $parse-mu:error1:
14400     # error("unexpected top-level command: " word-slice "\n")
14401     (write-buffered *(ebp+0xc) "unexpected top-level command: ")
14402     (write-slice-buffered *(ebp+0xc) %edx)
14403     (write-buffered *(ebp+0xc) "\n")
14404     (flush *(ebp+0xc))
14405     (stop *(ebp+0x10) 1)
14406     # never gets here
14407 
14408 $parse-mu:error2:
14409     # error(vars->top " vars not reclaimed after fn '" new-function->name "'\n")
14410     (write-int32-hex-buffered *(ebp+0xc) *ebx)
14411     (write-buffered *(ebp+0xc) " vars not reclaimed after fn '")
14412     (write-slice-buffered *(ebp+0xc) *eax)  # Function-name
14413     (write-buffered *(ebp+0xc) "'\n")
14414     (flush *(ebp+0xc))
14415     (stop *(ebp+0x10) 1)
14416     # never gets here
14417 
14418 # scenarios considered:
14419 # ✗ fn foo  # no block
14420 # ✓ fn foo {
14421 # ✗ fn foo { {
14422 # ✗ fn foo { }
14423 # ✗ fn foo { } {
14424 # ✗ fn foo x {
14425 # ✗ fn foo x: {
14426 # ✓ fn foo x: int {
14427 # ✓ fn foo x: int {
14428 # ✓ fn foo x: int -> _/eax: int {
14429 # TODO:
14430 #   disallow outputs of type `(... addr ...)`
14431 #   disallow inputs of type `(... addr ... addr ...)`
14432 populate-mu-function-header:  # first-line: (addr stream byte), out: (addr function), vars: (addr stack live-var), err: (addr buffered-file), ed: (addr exit-descriptor)
14433     # pseudocode:
14434     #   var word-slice: slice
14435     #   next-mu-token(first-line, word-slice)
14436     #   if slice-empty?(word-slice) abort
14437     #   assert(word-slice not in '{' '}' '->')
14438     #   out->name = slice-to-string(word-slice)
14439     #   ## inouts
14440     #   while true
14441     #     word-slice = next-mu-token(first-line)
14442     #     if slice-empty?(word-slice) abort
14443     #     if (word-slice == '{') goto done
14444     #     if (word-slice == '->') break
14445     #     assert(word-slice != '}')
14446     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
14447     #     assert(v->register == null)
14448     #     # v->block-depth is implicitly 0
14449     #     out->inouts = append(v, out->inouts)
14450     #     push(vars, {v, false})
14451     #   ## outputs
14452     #   while true
14453     #     word-slice = next-mu-token(first-line)
14454     #     if slice-empty?(word-slice) abort
14455     #     if (word-slice == '{') break
14456     #     assert(word-slice not in '}' '->')
14457     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
14458     #     assert(v->register != null)
14459     #     assert(v->name == "_")
14460     #     out->outputs = append(v, out->outputs)
14461     #   done:
14462     #
14463     # . prologue
14464     55/push-ebp
14465     89/<- %ebp 4/r32/esp
14466     # . save registers
14467     50/push-eax
14468     51/push-ecx
14469     52/push-edx
14470     53/push-ebx
14471     57/push-edi
14472     # edi = out
14473     8b/-> *(ebp+0xc) 7/r32/edi
14474     # var word-slice/ecx: slice
14475     68/push 0/imm32/end
14476     68/push 0/imm32/start
14477     89/<- %ecx 4/r32/esp
14478     # var v/ebx: (handle var)
14479     68/push 0/imm32
14480     68/push 0/imm32
14481     89/<- %ebx 4/r32/esp
14482     # read function name
14483     (next-mu-token *(ebp+8) %ecx)
14484     # error checking
14485     # if slice-empty?(word-slice) abort
14486     (slice-empty? %ecx)  # => eax
14487     3d/compare-eax-and 0/imm32/false
14488     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
14489     # if (word-slice == '{') abort
14490     (slice-equal? %ecx "{")   # => eax
14491     3d/compare-eax-and 0/imm32/false
14492     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
14493     # if (word-slice == '->') abort
14494     (slice-equal? %ecx "->")   # => eax
14495     3d/compare-eax-and 0/imm32/false
14496     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
14497     # if (word-slice == '}') abort
14498     (slice-equal? %ecx "}")   # => eax
14499     3d/compare-eax-and 0/imm32/false
14500     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
14501     # if word-slice already defined, abort
14502     (function-exists? %ecx)  # => eax
14503     3d/compare-eax-and 0/imm32/false
14504     0f 85/jump-if-!= $populate-mu-function-header:error-duplicate/disp32
14505     #
14506     (slice-starts-with? %ecx "break")  # => eax
14507     3d/compare-eax-and 0/imm32/false
14508     0f 85/jump-if-!= $populate-mu-function-header:error-break/disp32
14509     (slice-starts-with? %ecx "loop")  # => eax
14510     3d/compare-eax-and 0/imm32/false
14511     0f 85/jump-if-!= $populate-mu-function-header:error-loop/disp32
14512     (slice-equal? %ecx "lookup")  # => eax
14513     3d/compare-eax-and 0/imm32/false
14514     0f 85/jump-if-!= $populate-mu-function-header:error-lookup/disp32
14515     # save function name
14516     (slice-to-string Heap %ecx %edi)  # Function-name
14517     # save function inouts
14518     {
14519 $populate-mu-function-header:check-for-inout:
14520       (next-mu-token *(ebp+8) %ecx)
14521       # if slice-empty?(word-slice) abort
14522       (slice-empty? %ecx)  # => eax
14523       3d/compare-eax-and 0/imm32/false
14524       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
14525       # if (word-slice == '{') goto done
14526       (slice-equal? %ecx "{")   # => eax
14527       3d/compare-eax-and 0/imm32/false
14528       0f 85/jump-if-!= $populate-mu-function-header:done/disp32
14529       # if (word-slice == '->') break
14530       (slice-equal? %ecx "->")   # => eax
14531       3d/compare-eax-and 0/imm32/false
14532       0f 85/jump-if-!= break/disp32
14533       # if (word-slice == '}') abort
14534       (slice-equal? %ecx "}")   # => eax
14535       3d/compare-eax-and 0/imm32/false
14536       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
14537       # v = parse-var-with-type(word-slice, first-line)
14538       (lookup *edi *(edi+4))  # Function-name Function-name => eax
14539       (parse-var-with-type %ecx *(ebp+8) %ebx %eax *(ebp+0x14) *(ebp+0x18))
14540       # if (v->register != null) abort
14541       # . eax: (addr var) = lookup(v)
14542       (lookup *ebx *(ebx+4))  # => eax
14543       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
14544       0f 85/jump-if-!= $populate-mu-function-header:error2/disp32
14545       # if function name is not "main"
14546       #    and v->type contains an 'addr' anywhere except the start, abort
14547       {
14548         (lookup *edi *(edi+4))  # Function-name Function-name => eax
14549         (string-equal? %eax "main")  # => eax
14550         3d/compare-eax-and 0/imm32/false
14551         75/jump-if-!= break/disp8
14552         (lookup *ebx *(ebx+4))  # => eax
14553         (addr-payload-contains-addr? %eax)  # => eax
14554         3d/compare-eax-and 0/imm32/false
14555         0f 85/jump-if-!= $populate-mu-function-header:error-nested-addr-inout/disp32
14556       }
14557       # v->block-depth is implicitly 0
14558       #
14559       # out->inouts = append(v, out->inouts)
14560       8d/copy-address *(edi+8) 0/r32/eax  # Function-inouts
14561       (append-list Heap  *ebx *(ebx+4)  *(edi+8) *(edi+0xc)  %eax)  # Function-inouts, Function-inouts
14562       # push(vars, {v, false})
14563       (push *(ebp+0x10) *ebx)
14564       (push *(ebp+0x10) *(ebx+4))
14565       (push *(ebp+0x10) 0)  # false
14566       #
14567       e9/jump loop/disp32
14568     }
14569     # save function outputs
14570     {
14571 $populate-mu-function-header:check-for-out:
14572       (next-mu-token *(ebp+8) %ecx)
14573       # if slice-empty?(word-slice) abort
14574       (slice-empty? %ecx)  # => eax
14575       3d/compare-eax-and 0/imm32/false
14576       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
14577       # if (word-slice == '{') break
14578       (slice-equal? %ecx "{")   # => eax
14579       3d/compare-eax-and 0/imm32/false
14580       0f 85/jump-if-!= break/disp32
14581       # if (word-slice == '->') abort
14582       (slice-equal? %ecx "->")   # => eax
14583       3d/compare-eax-and 0/imm32/false
14584       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
14585       # if (word-slice == '}') abort
14586       (slice-equal? %ecx "}")   # => eax
14587       3d/compare-eax-and 0/imm32/false
14588       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
14589       # v = parse-var-with-type(word-slice, first-line)
14590       (lookup *edi *(edi+4))  # Function-name Function-name => eax
14591       (parse-var-with-type %ecx *(ebp+8) %ebx %eax *(ebp+0x14) *(ebp+0x18))
14592       # assert(var->register != null)
14593       # . eax: (addr var) = lookup(v)
14594       (lookup *ebx *(ebx+4))  # => eax
14595       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
14596       0f 84/jump-if-= $populate-mu-function-header:error3/disp32
14597       # if (var->name != "_") abort
14598       (lookup *eax *(eax+4))  # Var-name Var-name => eax
14599       (string-equal? %eax "_")  # => eax
14600       3d/compare-eax-and 0/imm32/false
14601       0f 84/jump-if-= $populate-mu-function-header:error4/disp32
14602       # if v->type is an addr, abort
14603       (lookup *ebx *(ebx+4))  # => eax
14604       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
14605       (is-mu-addr-type? %eax)  # => eax
14606       3d/compare-eax-and 0/imm32/false
14607       0f 85/jump-if-!= $populate-mu-function-header:error-addr-output/disp32
14608       # out->outputs = append(v, out->outputs)
14609       8d/copy-address *(edi+0x10) 0/r32/eax  # Function-outputs
14610       (append-list Heap  *ebx *(ebx+4)  *(edi+0x10) *(edi+0x14)  %eax)  # Function-outputs, Function-outputs
14611       #
14612       e9/jump loop/disp32
14613     }
14614 $populate-mu-function-header:done:
14615     (check-no-tokens-left *(ebp+8))
14616 $populate-mu-function-header:end:
14617     # . reclaim locals
14618     81 0/subop/add %esp 0x10/imm32
14619     # . restore registers
14620     5f/pop-to-edi
14621     5b/pop-to-ebx
14622     5a/pop-to-edx
14623     59/pop-to-ecx
14624     58/pop-to-eax
14625     # . epilogue
14626     89/<- %esp 5/r32/ebp
14627     5d/pop-to-ebp
14628     c3/return
14629 
14630 $populate-mu-function-header:error1:
14631     # error("function header not in form 'fn <name> {'")
14632     (write-buffered *(ebp+0x14) "function header not in form 'fn <name> [inouts] [-> outputs] {' -- '")
14633     (flush *(ebp+0x14))
14634     (rewind-stream *(ebp+8))
14635     (write-stream-data *(ebp+0x14) *(ebp+8))
14636     (write-buffered *(ebp+0x14) "'\n")
14637     (flush *(ebp+0x14))
14638     (stop *(ebp+0x18) 1)
14639     # never gets here
14640 
14641 $populate-mu-function-header:error2:
14642     # error("fn " fn ": function inout '" var "' cannot be in a register")
14643     (write-buffered *(ebp+0x14) "fn ")
14644     50/push-eax
14645     (lookup *edi *(edi+4))  # Function-name Function-name => eax
14646     (write-buffered *(ebp+0x14) %eax)
14647     58/pop-to-eax
14648     (write-buffered *(ebp+0x14) ": function inout '")
14649     (lookup *eax *(eax+4))  # Var-name Var-name => eax
14650     (write-buffered *(ebp+0x14) %eax)
14651     (write-buffered *(ebp+0x14) "' cannot be in a register")
14652     (flush *(ebp+0x14))
14653     (stop *(ebp+0x18) 1)
14654     # never gets here
14655 
14656 $populate-mu-function-header:error3:
14657     # error("fn " fn ": function output '" var "' must be in a register")
14658     (write-buffered *(ebp+0x14) "fn ")
14659     50/push-eax
14660     (lookup *edi *(edi+4))  # Function-name Function-name => eax
14661     (write-buffered *(ebp+0x14) %eax)
14662     58/pop-to-eax
14663     (write-buffered *(ebp+0x14) ": function output '")
14664     (lookup *ebx *(ebx+4))  # => eax
14665     (lookup *eax *(eax+4))  # Var-name Var-name => eax
14666     (write-buffered *(ebp+0x14) %eax)
14667     (write-buffered *(ebp+0x14) "' must be in a register, in instruction '")
14668     (rewind-stream *(ebp+8))
14669     (write-stream-data *(ebp+0x14) *(ebp+8))
14670     (write-buffered *(ebp+0x14) "'\n")
14671     (flush *(ebp+0x14))
14672     (stop *(ebp+0x18) 1)
14673     # never gets here
14674 
14675 $populate-mu-function-header:error4:
14676     # error("fn " fn ": function outputs cannot be named; rename '" var "' in the header to '_'")
14677     (write-buffered *(ebp+0x14) "fn ")
14678     50/push-eax
14679     (lookup *edi *(edi+4))  # Function-name Function-name => eax
14680     (write-buffered *(ebp+0x14) %eax)
14681     58/pop-to-eax
14682     (write-buffered *(ebp+0x14) ": function outputs cannot be named; rename '")
14683     (lookup *ebx *(ebx+4))  # => eax
14684     (lookup *eax *(eax+4))  # Var-name Var-name => eax
14685     (write-buffered *(ebp+0x14) %eax)
14686     (write-buffered *(ebp+0x14) "' in the header to '_'\n")
14687     (flush *(ebp+0x14))
14688     (stop *(ebp+0x18) 1)
14689     # never gets here
14690 
14691 $populate-mu-function-header:error-duplicate:
14692     (write-buffered *(ebp+0x14) "fn ")
14693     (write-slice-buffered *(ebp+0x14) %ecx)
14694     (write-buffered *(ebp+0x14) " defined more than once\n")
14695     (flush *(ebp+0x14))
14696     (stop *(ebp+0x18) 1)
14697     # never gets here
14698 
14699 $populate-mu-function-header:error-break:
14700     (write-buffered *(ebp+0x14) "Sorry, I've reserved all function names starting with 'break' for now. Please contact mu@akkartik.com.\n")
14701     (flush *(ebp+0x14))
14702     (stop *(ebp+0x18) 1)
14703     # never gets here
14704 
14705 $populate-mu-function-header:error-loop:
14706     (write-buffered *(ebp+0x14) "Sorry, I've reserved all function names starting with 'loop' for now. Please contact mu@akkartik.com.\n")
14707     (flush *(ebp+0x14))
14708     (stop *(ebp+0x18) 1)
14709     # never gets here
14710 
14711 $populate-mu-function-header:error-lookup:
14712     (write-buffered *(ebp+0x14) "cannot define a function called 'lookup'\n")
14713     (flush *(ebp+0x14))
14714     (stop *(ebp+0x18) 1)
14715     # never gets here
14716 
14717 $populate-mu-function-header:error-addr-output:
14718     # error("fn " fn ": output cannot have an addr type; that could allow unsafe addresses to escape the function")
14719     (write-buffered *(ebp+0x14) "fn ")
14720     50/push-eax
14721     (lookup *edi *(edi+4))  # Function-name Function-name => eax
14722     (write-buffered *(ebp+0x14) %eax)
14723     58/pop-to-eax
14724     (write-buffered *(ebp+0x14) ": output cannot have an addr type; that could allow unsafe addresses to escape the function\n")
14725     (flush *(ebp+0x14))
14726     (stop *(ebp+0x18) 1)
14727     # never gets here
14728 
14729 $populate-mu-function-header:error-nested-addr-inout:
14730     # error("fn " fn ": inout '" var "' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function")
14731     (write-buffered *(ebp+0x14) "fn ")
14732     (lookup *edi *(edi+4))  # Function-name Function-name => eax
14733     (write-buffered *(ebp+0x14) %eax)
14734     (write-buffered *(ebp+0x14) ": inout '")
14735     (lookup *ebx *(ebx+4))  # => eax
14736     (lookup *eax *(eax+4))  # Var-name Var-name => eax
14737     (write-buffered *(ebp+0x14) %eax)
14738     (write-buffered *(ebp+0x14) "' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function\n")
14739     (flush *(ebp+0x14))
14740     (stop *(ebp+0x18) 1)
14741     # never gets here
14742 
14743 # scenarios considered:
14744 # ✓ fn foo
14745 # ✗ fn foo {
14746 # ✓ fn foo x
14747 # ✓ fn foo x: int
14748 # ✓ fn foo x: int -> _/eax: int
14749 # TODO:
14750 #   disallow outputs of type `(... addr ...)`
14751 #   disallow inputs of type `(... addr ... addr ...)`
14752 populate-mu-function-signature:  # first-line: (addr stream byte), out: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
14753     # pseudocode:
14754     #   var word-slice: slice
14755     #   next-mu-token(first-line, word-slice)
14756     #   assert(word-slice not in '{' '}' '->')
14757     #   out->name = slice-to-string(word-slice)
14758     #   ## inouts
14759     #   while true
14760     #     word-slice = next-mu-token(first-line)
14761     #     if slice-empty?(word-slice) break
14762     #     if (word-slice == '->') break
14763     #     assert(word-slice not in '{' '}')
14764     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
14765     #     assert(v->register == null)
14766     #     # v->block-depth is implicitly 0
14767     #     out->inouts = append(v, out->inouts)
14768     #   ## outputs
14769     #   while true
14770     #     word-slice = next-mu-token(first-line)
14771     #     if slice-empty?(word-slice) break
14772     #     assert(word-slice not in '{' '}' '->')
14773     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
14774     #     assert(v->register != null)
14775     #     out->outputs = append(v, out->outputs)
14776     #
14777     # . prologue
14778     55/push-ebp
14779     89/<- %ebp 4/r32/esp
14780     # . save registers
14781     50/push-eax
14782     51/push-ecx
14783     52/push-edx
14784     53/push-ebx
14785     57/push-edi
14786     # edi = out
14787     8b/-> *(ebp+0xc) 7/r32/edi
14788     # var word-slice/ecx: slice
14789     68/push 0/imm32/end
14790     68/push 0/imm32/start
14791     89/<- %ecx 4/r32/esp
14792     # var v/ebx: (handle var)
14793     68/push 0/imm32
14794     68/push 0/imm32
14795     89/<- %ebx 4/r32/esp
14796     # read function name
14797     (next-mu-token *(ebp+8) %ecx)
14798     # error checking
14799     # if (word-slice == '{') abort
14800     (slice-equal? %ecx "{")   # => eax
14801     3d/compare-eax-and 0/imm32/false
14802     0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
14803     # if (word-slice == '->') abort
14804     (slice-equal? %ecx "->")   # => eax
14805     3d/compare-eax-and 0/imm32/false
14806     0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
14807     # if (word-slice == '}') abort
14808     (slice-equal? %ecx "}")   # => eax
14809     3d/compare-eax-and 0/imm32/false
14810     0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
14811     # if word-slice already defined, abort
14812     (function-exists? %ecx)  # => eax
14813     3d/compare-eax-and 0/imm32/false
14814     0f 85/jump-if-!= $populate-mu-function-signature:error-duplicate/disp32
14815     #
14816     (slice-starts-with? %ecx "break")  # => eax
14817     3d/compare-eax-and 0/imm32/false
14818     0f 85/jump-if-!= $populate-mu-function-signature:error-break/disp32
14819     (slice-starts-with? %ecx "loop")  # => eax
14820     3d/compare-eax-and 0/imm32/false
14821     0f 85/jump-if-!= $populate-mu-function-signature:error-loop/disp32
14822     # save function name
14823     (slice-to-string Heap %ecx %edi)  # Function-name
14824     # save function inouts
14825     {
14826 $populate-mu-function-signature:check-for-inout:
14827       (next-mu-token *(ebp+8) %ecx)
14828       (slice-empty? %ecx)  # => eax
14829       3d/compare-eax-and 0/imm32/false
14830       0f 85/jump-if-!= break/disp32
14831       # if (word-slice == '->') break
14832       (slice-equal? %ecx "->")   # => eax
14833       3d/compare-eax-and 0/imm32/false
14834       0f 85/jump-if-!= break/disp32
14835       # if (word-slice == '{') abort
14836       (slice-equal? %ecx "{")   # => eax
14837       3d/compare-eax-and 0/imm32/false
14838       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
14839       # if (word-slice == '}') abort
14840       (slice-equal? %ecx "}")   # => eax
14841       3d/compare-eax-and 0/imm32/false
14842       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
14843       # v = parse-var-with-type(word-slice, first-line)
14844       (lookup *edi *(edi+4))  # Function-name Function-name => eax
14845       (parse-var-with-type %ecx *(ebp+8) %ebx %eax *(ebp+0x10) *(ebp+0x14))
14846       # if (v->register != null) abort
14847       # . eax: (addr var) = lookup(v)
14848       (lookup *ebx *(ebx+4))  # => eax
14849       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
14850       0f 85/jump-if-!= $populate-mu-function-signature:error2/disp32
14851       # if function name is not "main"
14852       #    and v->type contains an 'addr' anywhere except the start, abort
14853       {
14854         (lookup *edi *(edi+4))  # Function-name Function-name => eax
14855         (string-equal? %eax "main")  # => eax
14856         3d/compare-eax-and 0/imm32/false
14857         75/jump-if-!= break/disp8
14858         (lookup *ebx *(ebx+4))  # => eax
14859         (addr-payload-contains-addr? %eax)  # => eax
14860         3d/compare-eax-and 0/imm32/false
14861         0f 85/jump-if-!= $populate-mu-function-signature:error-nested-addr-inout/disp32
14862       }
14863       # assert(v->register == null)
14864       # . eax: (addr var) = lookup(v)
14865       (lookup *ebx *(ebx+4))  # => eax
14866       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
14867       0f 85/jump-if-!= $populate-mu-function-signature:error2/disp32
14868       # v->block-depth is implicitly 0
14869       #
14870       # out->inouts = append(v, out->inouts)
14871       8d/copy-address *(edi+8) 0/r32/eax  # Function-inouts
14872       (append-list Heap  *ebx *(ebx+4)  *(edi+8) *(edi+0xc)  %eax)  # Function-inouts, Function-inouts
14873       #
14874       e9/jump loop/disp32
14875     }
14876     # save function outputs
14877     {
14878 $populate-mu-function-signature:check-for-out:
14879       (next-mu-token *(ebp+8) %ecx)
14880       (slice-empty? %ecx)  # => eax
14881       3d/compare-eax-and 0/imm32/false
14882       0f 85/jump-if-!= break/disp32
14883       # if (word-slice == '{') abort
14884       (slice-equal? %ecx "{")   # => eax
14885       3d/compare-eax-and 0/imm32/false
14886       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
14887       # if (word-slice == '->') abort
14888       (slice-equal? %ecx "->")   # => eax
14889       3d/compare-eax-and 0/imm32/false
14890       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
14891       # if (word-slice == '}') abort
14892       (slice-equal? %ecx "}")   # => eax
14893       3d/compare-eax-and 0/imm32/false
14894       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
14895       # v = parse-var-with-type(word-slice, first-line)
14896       (lookup *edi *(edi+4))  # Function-name Function-name => eax
14897       (parse-var-with-type %ecx *(ebp+8) %ebx %eax *(ebp+0x10) *(ebp+0x14))
14898       # assert(var->register != null)
14899       # . eax: (addr var) = lookup(v)
14900       (lookup *ebx *(ebx+4))  # => eax
14901       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
14902       0f 84/jump-if-= $populate-mu-function-signature:error3/disp32
14903       # if (var->name != "_") abort
14904       (lookup *eax *(eax+4))  # Var-name Var-name => eax
14905       (string-equal? %eax "_")  # => eax
14906       3d/compare-eax-and 0/imm32/false
14907       0f 84/jump-if-= $populate-mu-function-signature:error4/disp32
14908       # if function name is not "lookup"
14909       #    and v->type is an addr, abort
14910       {
14911         (lookup *edi *(edi+4))  # Function-name Function-name => eax
14912         (string-equal? %eax "lookup")  # => eax
14913         3d/compare-eax-and 0/imm32/false
14914         75/jump-if-!= break/disp8
14915         (lookup *ebx *(ebx+4))  # => eax
14916         (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
14917         (is-mu-addr-type? %eax)  # => eax
14918         3d/compare-eax-and 0/imm32/false
14919         0f 85/jump-if-!= $populate-mu-function-signature:error-addr-output/disp32
14920       }
14921       # out->outputs = append(v, out->outputs)
14922       8d/copy-address *(edi+0x10) 0/r32/eax  # Function-outputs
14923       (append-list Heap  *ebx *(ebx+4)  *(edi+0x10) *(edi+0x14)  %eax)  # Function-outputs, Function-outputs
14924       #
14925       e9/jump loop/disp32
14926     }
14927 $populate-mu-function-signature:done:
14928     (check-no-tokens-left *(ebp+8))
14929 $populate-mu-function-signature:end:
14930     # . reclaim locals
14931     81 0/subop/add %esp 0x10/imm32
14932     # . restore registers
14933     5f/pop-to-edi
14934     5b/pop-to-ebx
14935     5a/pop-to-edx
14936     59/pop-to-ecx
14937     58/pop-to-eax
14938     # . epilogue
14939     89/<- %esp 5/r32/ebp
14940     5d/pop-to-ebp
14941     c3/return
14942 
14943 $populate-mu-function-signature:error1:
14944     # error("function signature not in form 'fn <name> {'")
14945     (write-buffered *(ebp+0x10) "function signature not in form 'fn <name> [inouts] [-> outputs] {' -- '")
14946     (flush *(ebp+0x10))
14947     (rewind-stream *(ebp+8))
14948     (write-stream-data *(ebp+0x10) *(ebp+8))
14949     (write-buffered *(ebp+0x10) "'\n")
14950     (flush *(ebp+0x10))
14951     (stop *(ebp+0x14) 1)
14952     # never gets here
14953 
14954 $populate-mu-function-signature:error2:
14955     # error("fn " fn ": function inout '" var "' cannot be in a register")
14956     (write-buffered *(ebp+0x10) "fn ")
14957     50/push-eax
14958     (lookup *edi *(edi+4))  # Function-name Function-name => eax
14959     (write-buffered *(ebp+0x10) %eax)
14960     58/pop-to-eax
14961     (write-buffered *(ebp+0x10) ": function inout '")
14962     (lookup *eax *(eax+4))  # Var-name Var-name => eax
14963     (write-buffered *(ebp+0x10) %eax)
14964     (write-buffered *(ebp+0x10) "' cannot be in a register")
14965     (flush *(ebp+0x10))
14966     (stop *(ebp+0x14) 1)
14967     # never gets here
14968 
14969 $populate-mu-function-signature:error3:
14970     # error("fn " fn ": function output '" var "' must be in a register")
14971     (write-buffered *(ebp+0x10) "fn ")
14972     50/push-eax
14973     (lookup *edi *(edi+4))  # Function-name Function-name => eax
14974     (write-buffered *(ebp+0x10) %eax)
14975     58/pop-to-eax
14976     (write-buffered *(ebp+0x10) ": function output '")
14977     (lookup *ebx *(ebx+4))  # => eax
14978     (lookup *eax *(eax+4))  # Var-name Var-name => eax
14979     (write-buffered *(ebp+0x10) %eax)
14980     (write-buffered *(ebp+0x10) "' must be in a register, in instruction '")
14981     (rewind-stream *(ebp+8))
14982     (write-stream-data *(ebp+0x10) *(ebp+8))
14983     (write-buffered *(ebp+0x10) "'\n")
14984     (flush *(ebp+0x10))
14985     (stop *(ebp+0x14) 1)
14986     # never gets here
14987 
14988 $populate-mu-function-signature:error4:
14989     # error("fn " fn ": function outputs cannot be named; rename '" var "' in the header to '_'")
14990     (write-buffered *(ebp+0x10) "fn ")
14991     50/push-eax
14992     (lookup *edi *(edi+4))  # Function-name Function-name => eax
14993     (write-buffered *(ebp+0x10) %eax)
14994     58/pop-to-eax
14995     (write-buffered *(ebp+0x10) ": function outputs cannot be named; rename '")
14996     (lookup *ebx *(ebx+4))  # => eax
14997     (lookup *eax *(eax+4))  # Var-name Var-name => eax
14998     (write-buffered *(ebp+0x10) %eax)
14999     (write-buffered *(ebp+0x10) "' in the header to '_'\n")
15000     (flush *(ebp+0x10))
15001     (stop *(ebp+0x14) 1)
15002     # never gets here
15003 
15004 $populate-mu-function-signature:error-duplicate:
15005     (write-buffered *(ebp+0x10) "fn ")
15006     (write-slice-buffered *(ebp+0x10) %ecx)
15007     (write-buffered *(ebp+0x10) " defined more than once\n")
15008     (flush *(ebp+0x10))
15009     (stop *(ebp+0x14) 1)
15010     # never gets here
15011 
15012 $populate-mu-function-signature:error-break:
15013     (write-buffered *(ebp+0x10) "Sorry, I've reserved all function names starting with 'break' for now. Please contact mu@akkartik.com.\n")
15014     (flush *(ebp+0x10))
15015     (stop *(ebp+0x14) 1)
15016     # never gets here
15017 
15018 $populate-mu-function-signature:error-loop:
15019     (write-buffered *(ebp+0x10) "Sorry, I've reserved all function names starting with 'loop' for now. Please contact mu@akkartik.com.\n")
15020     (flush *(ebp+0x10))
15021     (stop *(ebp+0x14) 1)
15022     # never gets here
15023 
15024 $populate-mu-function-signature:error-addr-output:
15025     # error("fn " fn ": output cannot have an addr type; that could allow unsafe addresses to escape the function")
15026     (write-buffered *(ebp+0x10) "fn ")
15027     50/push-eax
15028     (lookup *edi *(edi+4))  # Function-name Function-name => eax
15029     (write-buffered *(ebp+0x10) %eax)
15030     58/pop-to-eax
15031     (write-buffered *(ebp+0x10) ": output cannot have an addr type; that could allow unsafe addresses to escape the function\n")
15032     (flush *(ebp+0x10))
15033     (stop *(ebp+0x14) 1)
15034     # never gets here
15035 
15036 $populate-mu-function-signature:error-nested-addr-inout:
15037     # error("fn " fn ": inout '" var "' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function")
15038     (write-buffered *(ebp+0x10) "fn ")
15039     (lookup *edi *(edi+4))  # Function-name Function-name => eax
15040     (write-buffered *(ebp+0x10) %eax)
15041     (write-buffered *(ebp+0x10) ": inout '")
15042     (lookup *ebx *(ebx+4))  # => eax
15043     (lookup *eax *(eax+4))  # Var-name Var-name => eax
15044     (write-buffered *(ebp+0x10) %eax)
15045     (write-buffered *(ebp+0x10) "' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function\n")
15046     (flush *(ebp+0x10))
15047     (stop *(ebp+0x14) 1)
15048     # never gets here
15049 
15050 addr-payload-contains-addr?:  # v: (addr var) -> result/eax: boolean
15051     # . prologue
15052     55/push-ebp
15053     89/<- %ebp 4/r32/esp
15054     # var t/eax: (addr type-tree) = v->type
15055     8b/-> *(ebp+8) 0/r32/eax
15056     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
15057     # if t->right contains addr, return true
15058     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
15059     (type-tree-contains? %eax 2)  # addr => eax
15060     # we don't have to look at t->left as long as it's guaranteed to be an atom
15061 $addr-payload-contains-addr?:end:
15062     # . epilogue
15063     89/<- %esp 5/r32/ebp
15064     5d/pop-to-ebp
15065     c3/return
15066 
15067 type-tree-contains?:  # t: (addr type-tree), n: type-id -> result/eax: boolean
15068     # . prologue
15069     55/push-ebp
15070     89/<- %ebp 4/r32/esp
15071     # . save registers
15072     51/push-ecx
15073     # if t is null, return false
15074     8b/-> *(ebp+8) 0/r32/eax
15075     3d/compare-eax-and 0/imm32
15076     0f 84/jump-if-= $type-tree-contains?:end/disp32  # eax changes type
15077     # if t is an atom, return (t->value == n)
15078     81 7/subop/compare *eax 0/imm32/false
15079     {
15080       74/jump-if-= break/disp8
15081       8b/-> *(ebp+0xc) 1/r32/ecx
15082       39/compare *(eax+4) 1/r32/ecx  # Type-tree-value
15083       0f 94/set-if-= %al
15084       81 4/subop/and %eax 0xff/imm32
15085       eb/jump $type-tree-contains?:end/disp8
15086     }
15087     # if t->left contains n, return true
15088     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
15089     (type-tree-contains? %eax *(ebp+0xc))  # => eax
15090     3d/compare-eax-and 0/imm32/false
15091     75/jump-if-!= $type-tree-contains?:end/disp8
15092     # otherwise return whether t->right contains n
15093     8b/-> *(ebp+8) 0/r32/eax
15094     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
15095     (type-tree-contains? %eax *(ebp+0xc))  # => eax
15096 $type-tree-contains?:end:
15097     # . restore registers
15098     59/pop-to-ecx
15099     # . epilogue
15100     89/<- %esp 5/r32/ebp
15101     5d/pop-to-ebp
15102     c3/return
15103 
15104 function-exists?:  # s: (addr slice) -> result/eax: boolean
15105     # . prologue
15106     55/push-ebp
15107     89/<- %ebp 4/r32/esp
15108     # . save registers
15109     51/push-ecx
15110     # var curr/ecx: (addr function) = functions
15111     (lookup *_Program-functions *_Program-functions->payload)  # => eax
15112     89/<- %ecx 0/r32/eax
15113     {
15114       # if (curr == null) break
15115       81 7/subop/compare %ecx 0/imm32
15116       74/jump-if-= break/disp8
15117       # if (curr->name == s) return true
15118       {
15119         (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
15120         (slice-equal? *(ebp+8) %eax)  # => eax
15121         3d/compare-eax-and 0/imm32/false
15122         74/jump-if-= break/disp8
15123         b8/copy-to-eax 1/imm32/true
15124         e9/jump $function-exists?:end/disp32
15125       }
15126       # curr = curr->next
15127       (lookup *(ecx+0x20) *(ecx+0x24))  # Function-next Function-next => eax
15128       89/<- %ecx 0/r32/eax
15129       #
15130       eb/jump loop/disp8
15131     }
15132     # var curr/ecx: (addr function) = signatures
15133     (lookup *_Program-signatures *_Program-signatures->payload)  # => eax
15134     89/<- %ecx 0/r32/eax
15135     {
15136       # if (curr == null) break
15137       81 7/subop/compare %ecx 0/imm32
15138       74/jump-if-= break/disp8
15139       # if (curr->name == s) return true
15140       {
15141         (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
15142         (slice-equal? *(ebp+8) %eax)  # => eax
15143         3d/compare-eax-and 0/imm32/false
15144         74/jump-if-= break/disp8
15145         b8/copy-to-eax 1/imm32/true
15146         eb/jump $function-exists?:end/disp8
15147       }
15148       # curr = curr->next
15149       (lookup *(ecx+0x20) *(ecx+0x24))  # Function-next Function-next => eax
15150       89/<- %ecx 0/r32/eax
15151       #
15152       eb/jump loop/disp8
15153     }
15154     # return false
15155     b8/copy-to-eax 0/imm32/false
15156 $function-exists?:end:
15157     # . restore registers
15158     59/pop-to-ecx
15159     # . epilogue
15160     89/<- %esp 5/r32/ebp
15161     5d/pop-to-ebp
15162     c3/return
15163 
15164 test-function-header-with-arg:
15165     # . prologue
15166     55/push-ebp
15167     89/<- %ebp 4/r32/esp
15168     # setup
15169     8b/-> *Primitive-type-ids 0/r32/eax
15170     89/<- *Type-id 0/r32/eax  # stream-write
15171     c7 0/subop/copy *_Program-functions 0/imm32
15172     c7 0/subop/copy *_Program-functions->payload 0/imm32
15173     c7 0/subop/copy *_Program-types 0/imm32
15174     c7 0/subop/copy *_Program-types->payload 0/imm32
15175     c7 0/subop/copy *_Program-signatures 0/imm32
15176     c7 0/subop/copy *_Program-signatures->payload 0/imm32
15177     (clear-stream _test-input-stream)
15178     (write _test-input-stream "foo n: int {\n")
15179     # var result/ecx: function
15180     2b/subtract *Function-size 4/r32/esp
15181     89/<- %ecx 4/r32/esp
15182     (zero-out %ecx *Function-size)
15183     # var vars/ebx: (stack live-var 16)
15184     81 5/subop/subtract %esp 0xc0/imm32
15185     68/push 0xc0/imm32/size
15186     68/push 0/imm32/top
15187     89/<- %ebx 4/r32/esp
15188     # convert
15189     (populate-mu-function-header _test-input-stream %ecx %ebx Stderr 0)
15190     # check result->name
15191     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
15192     (check-strings-equal %eax "foo" "F - test-function-header-with-arg/name")
15193     # var v/edx: (addr var) = result->inouts->value
15194     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
15195     (lookup *eax *(eax+4))  # List-value List-value => eax
15196     89/<- %edx 0/r32/eax
15197     # check v->name
15198     (lookup *edx *(edx+4))  # Var-name Var-name => eax
15199     (check-strings-equal %eax "n" "F - test-function-header-with-arg/inout:0")
15200     # check v->type
15201     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
15202     (check-ints-equal *eax 1 "F - test-function-header-with-arg/inout:0/type:0")  # Type-tree-is-atom
15203     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-arg/inout:0/type:1")  # Type-tree-value
15204     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-arg/inout:0/type:2")  # Type-tree-right
15205     # . epilogue
15206     89/<- %esp 5/r32/ebp
15207     5d/pop-to-ebp
15208     c3/return
15209 
15210 test-function-header-with-multiple-args:
15211     # . prologue
15212     55/push-ebp
15213     89/<- %ebp 4/r32/esp
15214     # setup
15215     8b/-> *Primitive-type-ids 0/r32/eax
15216     89/<- *Type-id 0/r32/eax  # stream-write
15217     c7 0/subop/copy *_Program-functions 0/imm32
15218     c7 0/subop/copy *_Program-functions->payload 0/imm32
15219     c7 0/subop/copy *_Program-types 0/imm32
15220     c7 0/subop/copy *_Program-types->payload 0/imm32
15221     c7 0/subop/copy *_Program-signatures 0/imm32
15222     c7 0/subop/copy *_Program-signatures->payload 0/imm32
15223     (clear-stream _test-input-stream)
15224     (write _test-input-stream "foo a: int, b: int c: int {\n")
15225     # result/ecx: function
15226     2b/subtract *Function-size 4/r32/esp
15227     89/<- %ecx 4/r32/esp
15228     (zero-out %ecx *Function-size)
15229     # var vars/ebx: (stack live-var 16)
15230     81 5/subop/subtract %esp 0xc0/imm32
15231     68/push 0xc0/imm32/size
15232     68/push 0/imm32/top
15233     89/<- %ebx 4/r32/esp
15234     # convert
15235     (populate-mu-function-header _test-input-stream %ecx %ebx Stderr 0)
15236     # check result->name
15237     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
15238     (check-strings-equal %eax "foo" "F - test-function-header-with-multiple-args/name")
15239     # var inouts/edx: (addr list var) = lookup(result->inouts)
15240     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
15241     89/<- %edx 0/r32/eax
15242 $test-function-header-with-multiple-args:inout0:
15243     # var v/ebx: (addr var) = lookup(inouts->value)
15244     (lookup *edx *(edx+4))  # List-value List-value => eax
15245     89/<- %ebx 0/r32/eax
15246     # check v->name
15247     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
15248     (check-strings-equal %eax "a" "F - test-function-header-with-multiple-args/inout:0")  # Var-name
15249     # check v->type
15250     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
15251     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args/inout:0/type:0")  # Type-tree-is-atom
15252     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args/inout:0/type:1")  # Type-tree-value
15253     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args/inout:0/type:2")  # Type-tree-right
15254 $test-function-header-with-multiple-args:inout1:
15255     # inouts = lookup(inouts->next)
15256     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
15257     89/<- %edx 0/r32/eax
15258     # v = lookup(inouts->value)
15259     (lookup *edx *(edx+4))  # List-value List-value => eax
15260     89/<- %ebx 0/r32/eax
15261     # check v->name
15262     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
15263     (check-strings-equal %eax "b" "F - test-function-header-with-multiple-args/inout:1")  # Var-name
15264     # check v->type
15265     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
15266     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args/inout:1/type:0")  # Type-tree-is-atom
15267     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args/inout:1/type:1")  # Type-tree-value
15268     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args/inout:1/type:2")  # Type-tree-right
15269 $test-function-header-with-multiple-args:inout2:
15270     # inouts = lookup(inouts->next)
15271     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
15272     89/<- %edx 0/r32/eax
15273     # v = lookup(inouts->value)
15274     (lookup *edx *(edx+4))  # List-value List-value => eax
15275     89/<- %ebx 0/r32/eax
15276     # check v->name
15277     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
15278     (check-strings-equal %eax "c" "F - test-function-header-with-multiple-args/inout:2")  # Var-name
15279     # check v->type
15280     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
15281     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args/inout:2/type:0")  # Type-tree-is-atom
15282     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args/inout:2/type:1")  # Type-tree-value
15283     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args/inout:2/type:2")  # Type-tree-right
15284     # . epilogue
15285     89/<- %esp 5/r32/ebp
15286     5d/pop-to-ebp
15287     c3/return
15288 
15289 test-function-header-with-multiple-args-and-outputs:
15290     # . prologue
15291     55/push-ebp
15292     89/<- %ebp 4/r32/esp
15293     # setup
15294     8b/-> *Primitive-type-ids 0/r32/eax
15295     89/<- *Type-id 0/r32/eax  # stream-write
15296     c7 0/subop/copy *_Program-functions 0/imm32
15297     c7 0/subop/copy *_Program-functions->payload 0/imm32
15298     c7 0/subop/copy *_Program-types 0/imm32
15299     c7 0/subop/copy *_Program-types->payload 0/imm32
15300     c7 0/subop/copy *_Program-signatures 0/imm32
15301     c7 0/subop/copy *_Program-signatures->payload 0/imm32
15302     (clear-stream _test-input-stream)
15303     (write _test-input-stream "foo a: int, b: int, c: int -> _/ecx: int _/edx: int {\n")
15304     # result/ecx: function
15305     2b/subtract *Function-size 4/r32/esp
15306     89/<- %ecx 4/r32/esp
15307     (zero-out %ecx *Function-size)
15308     # var vars/ebx: (stack live-var 16)
15309     81 5/subop/subtract %esp 0xc0/imm32
15310     68/push 0xc0/imm32/size
15311     68/push 0/imm32/top
15312     89/<- %ebx 4/r32/esp
15313     # convert
15314     (populate-mu-function-header _test-input-stream %ecx %ebx Stderr 0)
15315     # check result->name
15316     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
15317     (check-strings-equal %eax "foo" "F - test-function-header-with-multiple-args-and-outputs/name")
15318     # var inouts/edx: (addr list var) = lookup(result->inouts)
15319     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
15320     89/<- %edx 0/r32/eax
15321 $test-function-header-with-multiple-args-and-outputs:inout0:
15322     # var v/ebx: (addr var) = lookup(inouts->value)
15323     (lookup *edx *(edx+4))  # List-value List-value => eax
15324     89/<- %ebx 0/r32/eax
15325     # check v->name
15326     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
15327     (check-strings-equal %eax "a" "F - test-function-header-with-multiple-args-and-outputs/inout:0")
15328     # check v->type
15329     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
15330     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:0")  # Type-tree-is-atom
15331     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:1")  # Type-tree-value
15332     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:2")  # Type-tree-right
15333 $test-function-header-with-multiple-args-and-outputs:inout1:
15334     # inouts = lookup(inouts->next)
15335     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
15336     89/<- %edx 0/r32/eax
15337     # v = lookup(inouts->value)
15338     (lookup *edx *(edx+4))  # List-value List-value => eax
15339     89/<- %ebx 0/r32/eax
15340     # check v->name
15341     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
15342     (check-strings-equal %eax "b" "F - test-function-header-with-multiple-args-and-outputs/inout:1")
15343     # check v->type
15344     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
15345     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:0")  # Type-tree-is-atom
15346     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:1")  # Type-tree-value
15347     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:2")  # Type-tree-right
15348 $test-function-header-with-multiple-args-and-outputs:inout2:
15349     # inouts = lookup(inouts->next)
15350     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
15351     89/<- %edx 0/r32/eax
15352     # v = lookup(inouts->value)
15353     (lookup *edx *(edx+4))  # List-value List-value => eax
15354     89/<- %ebx 0/r32/eax
15355     # check v->name
15356     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
15357     (check-strings-equal %eax "c" "F - test-function-header-with-multiple-args-and-outputs/inout:2")
15358     # check v->type
15359     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
15360     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:0")  # Type-tree-is-atom
15361     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:1")  # Type-tree-value
15362     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:2")  # Type-tree-right
15363 $test-function-header-with-multiple-args-and-outputs:out0:
15364     # var outputs/edx: (addr list var) = lookup(result->outputs)
15365     (lookup *(ecx+0x10) *(ecx+0x14))  # Function-outputs Function-outputs => eax
15366     89/<- %edx 0/r32/eax
15367     # v = lookup(outputs->value)
15368     (lookup *edx *(edx+4))  # List-value List-value => eax
15369     89/<- %ebx 0/r32/eax
15370     # check v->name
15371     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
15372     (check-strings-equal %eax "_" "F - test-function-header-with-multiple-args-and-outputs/output:0")
15373     # check v->register
15374     (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
15375     (check-strings-equal %eax "ecx" "F - test-function-header-with-multiple-args-and-outputs/output:0/register")
15376     # check v->type
15377     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
15378     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:0")  # Type-tree-is-atom
15379     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:1")  # Type-tree-value
15380     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:2")  # Type-tree-right
15381 $test-function-header-with-multiple-args-and-outputs:out1:
15382     # outputs = lookup(outputs->next)
15383     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
15384     89/<- %edx 0/r32/eax
15385     # v = lookup(inouts->value)
15386     (lookup *edx *(edx+4))  # List-value List-value => eax
15387     89/<- %ebx 0/r32/eax
15388     # check v->name
15389     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
15390     (check-strings-equal %eax "_" "F - test-function-header-with-multiple-args-and-outputs/output:1")
15391     # check v->register
15392     (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
15393     (check-strings-equal %eax "edx" "F - test-function-header-with-multiple-args-and-outputs/output:1/register")
15394     # check v->type
15395     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
15396     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:0")  # Type-tree-is-atom
15397     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:1")  # Type-tree-value
15398     (check-ints-equal *(eax+0c) 0 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:2")  # Type-tree-right
15399     # . epilogue
15400     89/<- %esp 5/r32/ebp
15401     5d/pop-to-ebp
15402     c3/return
15403 
15404 # format for variables with types
15405 #   x: int
15406 #   x: int,
15407 #   x/eax: int
15408 #   x/eax: int,
15409 # ignores at most one trailing comma
15410 # WARNING: modifies name
15411 parse-var-with-type:  # name: (addr slice), first-line: (addr stream byte), out: (addr handle var), fn-name: (addr array byte), err: (addr buffered-file), ed: (addr exit-descriptor)
15412     # pseudocode:
15413     #   var s: slice
15414     #   if (!slice-ends-with(name, ":"))
15415     #     abort
15416     #   --name->end to skip ':'
15417     #   next-token-from-slice(name->start, name->end, '/', s)
15418     #   new-var-from-slice(s, out)
15419     #   ## register
15420     #   next-token-from-slice(s->end, name->end, '/', s)
15421     #   if (!slice-empty?(s))
15422     #     out->register = slice-to-string(s)
15423     #   ## type
15424     #   var type: (handle type-tree) = parse-type(first-line)
15425     #   out->type = type
15426     #
15427     # . prologue
15428     55/push-ebp
15429     89/<- %ebp 4/r32/esp
15430     # . save registers
15431     50/push-eax
15432     51/push-ecx
15433     52/push-edx
15434     53/push-ebx
15435     56/push-esi
15436     57/push-edi
15437     # esi = name
15438     8b/-> *(ebp+8) 6/r32/esi
15439     # if (!slice-ends-with?(name, ":")) abort
15440     8b/-> *(esi+4) 1/r32/ecx  # Slice-end
15441     49/decrement-ecx
15442     8a/copy-byte *ecx 1/r32/CL
15443     81 4/subop/and %ecx 0xff/imm32
15444     81 7/subop/compare %ecx 0x3a/imm32/colon
15445     0f 85/jump-if-!= $parse-var-with-type:abort/disp32
15446     # --name->end to skip ':'
15447     ff 1/subop/decrement *(esi+4)
15448     # var s/ecx: slice
15449     68/push 0/imm32/end
15450     68/push 0/imm32/start
15451     89/<- %ecx 4/r32/esp
15452 $parse-var-with-type:parse-name:
15453     (next-token-from-slice *esi *(esi+4) 0x2f %ecx)  # Slice-start, Slice-end, '/'
15454 $parse-var-with-type:create-var:
15455     # new-var-from-slice(s, out)
15456     (new-var-from-slice Heap %ecx *(ebp+0x10))
15457     # save out->register
15458 $parse-var-with-type:save-register:
15459     # . var out-addr/edi: (addr var) = lookup(*out)
15460     8b/-> *(ebp+0x10) 7/r32/edi
15461     (lookup *edi *(edi+4))  # => eax
15462     89/<- %edi 0/r32/eax
15463     # . s = next-token(...)
15464     (next-token-from-slice *(ecx+4) *(esi+4) 0x2f %ecx)  # s->end, name->end, '/'
15465     # . if (!slice-empty?(s)) out->register = slice-to-string(s)
15466     {
15467 $parse-var-with-type:write-register:
15468       (slice-empty? %ecx)  # => eax
15469       3d/compare-eax-and 0/imm32/false
15470       75/jump-if-!= break/disp8
15471       # out->register = slice-to-string(s)
15472       8d/copy-address *(edi+0x18) 0/r32/eax  # Var-register
15473       (slice-to-string Heap %ecx %eax)
15474     }
15475 $parse-var-with-type:save-type:
15476     8d/copy-address *(edi+8) 0/r32/eax  # Var-type
15477     (parse-type Heap *(ebp+0xc) %eax *(ebp+0x18) *(ebp+0x1c))
15478 $parse-var-with-type:check-register:
15479     (lookup *(edi+0x18) *(edi+0x1c))  # Var-register Var-register => eax
15480     3d/compare-eax-and 0/imm32
15481     74/jump-if-= $parse-var-with-type:end/disp8
15482     (is-float-register? %eax)  # => eax
15483     {
15484       3d/compare-eax-and 0/imm32/false
15485       74/jump-if-= break/disp8
15486       # var is in a float register; ensure type is float
15487       (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
15488       (is-simple-mu-type? %eax 0xf)  # float => eax
15489       3d/compare-eax-and 0/imm32/false
15490       0f 84/jump-if-= $parse-var-with-type:error-non-float-in-floating-point-register/disp32
15491       eb/jump $parse-var-with-type:end/disp8
15492     }
15493     # var is not in a float register; ensure type is not float
15494     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
15495     (is-simple-mu-type? %eax 0xf)  # float => eax
15496     3d/compare-eax-and 0/imm32/false
15497     0f 85/jump-if-!= $parse-var-with-type:error-float-in-integer-register/disp32
15498 $parse-var-with-type:end:
15499     # . reclaim locals
15500     81 0/subop/add %esp 8/imm32
15501     # . restore registers
15502     5f/pop-to-edi
15503     5e/pop-to-esi
15504     5b/pop-to-ebx
15505     5a/pop-to-edx
15506     59/pop-to-ecx
15507     58/pop-to-eax
15508     # . epilogue
15509     89/<- %esp 5/r32/ebp
15510     5d/pop-to-ebp
15511     c3/return
15512 
15513 $parse-var-with-type:abort:
15514     # error("fn " fn ": var should have form 'name: type' in '" line "'\n")
15515     (write-buffered *(ebp+0x18) "fn ")
15516     (write-buffered *(ebp+0x18) *(ebp+0x14))
15517     (write-buffered *(ebp+0x18) ": var should have form 'name: type' in '")
15518     (flush *(ebp+0x18))
15519     (rewind-stream *(ebp+0xc))
15520     (write-stream-data *(ebp+0x18) *(ebp+0xc))
15521     (write-buffered *(ebp+0x18) "'\n")
15522     (flush *(ebp+0x18))
15523     (stop *(ebp+0x1c) 1)
15524     # never gets here
15525 
15526 $parse-var-with-type:error-float-in-integer-register:
15527     # error("fn " fn ": float var '" var "' should be in a floating-point register\n")
15528     (write-buffered *(ebp+0x18) "fn ")
15529     (write-buffered *(ebp+0x18) *(ebp+0x14))
15530     (write-buffered *(ebp+0x18) ": float var '")
15531     (lookup *edi *(edi+4))  # Var-name Var-name => eax
15532     (write-buffered *(ebp+0x18) %eax)
15533     (write-buffered *(ebp+0x18) "' should be in a floating-point register\n")
15534     (flush *(ebp+0x18))
15535     (stop *(ebp+0x1c) 1)
15536     # never gets here
15537 
15538 $parse-var-with-type:error-non-float-in-floating-point-register:
15539     # error("fn " fn ": non-float var '" var "' should be in an integer register\n")
15540     (write-buffered *(ebp+0x18) "fn ")
15541     (write-buffered *(ebp+0x18) *(ebp+0x14))
15542     (write-buffered *(ebp+0x18) ": non-float var '")
15543     (lookup *edi *(edi+4))  # Var-name Var-name => eax
15544     (write-buffered *(ebp+0x18) %eax)
15545     (write-buffered *(ebp+0x18) "' should be in an integer register\n")
15546     (flush *(ebp+0x18))
15547     (stop *(ebp+0x1c) 1)
15548     # never gets here
15549 
15550 is-float-register?:  # r: (addr array byte) -> result/eax: boolean
15551     # . prologue
15552     55/push-ebp
15553     89/<- %ebp 4/r32/esp
15554     #
15555     (get Mu-registers-unique *(ebp+8) 0xc "Mu-registers-unique")  # => eax
15556     81 7/subop/compare *eax 8/imm32/start-of-floating-point-registers
15557     0f 9d/set-if->= %al
15558     81 4/subop/and %eax 0xff/imm32
15559 $is-float-register?:end:
15560     # . epilogue
15561     89/<- %esp 5/r32/ebp
15562     5d/pop-to-ebp
15563     c3/return
15564 
15565 parse-type:  # ad: (addr allocation-descriptor), in: (addr stream byte), out: (addr handle type-tree), err: (addr buffered-file), ed: (addr exit-descriptor)
15566     # pseudocode:
15567     #   var s: slice = next-mu-token(in)
15568     #   assert s != ""
15569     #   assert s != "->"
15570     #   assert s != "{"
15571     #   assert s != "}"
15572     #   if s == ")"
15573     #     return
15574     #   out = allocate(Type-tree)
15575     #   if s != "("
15576     #     HACK: if s is an int, parse and return it
15577     #     out->is-atom? = true
15578     #     if (s[0] == "_")
15579     #       out->value = type-parameter
15580     #       out->parameter-name = slice-to-string(ad, s)
15581     #     else
15582     #       out->value = pos-or-insert-slice(Type-id, s)
15583     #     return
15584     #   out->left = parse-type(ad, in)
15585     #   out->right = parse-type-tree(ad, in)
15586     #
15587     # . prologue
15588     55/push-ebp
15589     89/<- %ebp 4/r32/esp
15590     # . save registers
15591     50/push-eax
15592     51/push-ecx
15593     52/push-edx
15594     # clear out
15595     (zero-out *(ebp+0x10) *Handle-size)
15596     # var s/ecx: slice
15597     68/push 0/imm32
15598     68/push 0/imm32
15599     89/<- %ecx 4/r32/esp
15600     # s = next-mu-token(in)
15601     (next-mu-token *(ebp+0xc) %ecx)
15602 #?     (write-buffered Stderr "tok: ")
15603 #?     (write-slice-buffered Stderr %ecx)
15604 #?     (write-buffered Stderr "$\n")
15605 #?     (flush Stderr)
15606     # assert s != ""
15607     (slice-equal? %ecx "")  # => eax
15608     3d/compare-eax-and 0/imm32/false
15609     0f 85/jump-if-!= $parse-type:abort/disp32
15610     # assert s != "{"
15611     (slice-equal? %ecx "{")  # => eax
15612     3d/compare-eax-and 0/imm32/false
15613     0f 85/jump-if-!= $parse-type:abort/disp32
15614     # assert s != "}"
15615     (slice-equal? %ecx "}")  # => eax
15616     3d/compare-eax-and 0/imm32/false
15617     0f 85/jump-if-!= $parse-type:abort/disp32
15618     # assert s != "->"
15619     (slice-equal? %ecx "->")  # => eax
15620     3d/compare-eax-and 0/imm32/false
15621     0f 85/jump-if-!= $parse-type:abort/disp32
15622     # if (s == ")") return
15623     (slice-equal? %ecx ")")  # => eax
15624     3d/compare-eax-and 0/imm32/false
15625     0f 85/jump-if-!= $parse-type:end/disp32
15626     # out = new tree
15627     (allocate *(ebp+8) *Type-tree-size *(ebp+0x10))
15628     # var out-addr/edx: (addr type-tree) = lookup(*out)
15629     8b/-> *(ebp+0x10) 2/r32/edx
15630     (lookup *edx *(edx+4))  # => eax
15631     89/<- %edx 0/r32/eax
15632     {
15633       # if (s != "(") break
15634       (slice-equal? %ecx "(")  # => eax
15635       3d/compare-eax-and 0/imm32/false
15636       0f 85/jump-if-!= break/disp32
15637       # if s is a number, store it in the type's size field
15638       {
15639 $parse-type:check-for-int:
15640         # var tmp/eax: byte = *s->slice
15641         8b/-> *ecx 0/r32/eax
15642         8a/copy-byte *eax 0/r32/AL
15643         81 4/subop/and %eax 0xff/imm32
15644         # TODO: raise an error on `var x: (array int a)`
15645         (is-decimal-digit? %eax)  # => eax
15646         3d/compare-eax-and 0/imm32/false
15647         74/jump-if-= break/disp8
15648         #
15649         (is-hex-int? %ecx)  # => eax
15650         3d/compare-eax-and 0/imm32/false
15651         74/jump-if-= break/disp8
15652 $parse-type:int:
15653         (check-mu-hex-int %ecx *(ebp+0x14) *(ebp+0x18))
15654         (parse-hex-int-from-slice %ecx)  # => eax
15655         c7 0/subop/copy *(edx+4) 9/imm32/type-id-array-capacity  # Type-tree-value
15656         89/<- *(edx+8) 0/r32/eax  # Type-tree-value-size
15657         e9/jump $parse-type:end/disp32
15658       }
15659 $parse-type:atom:
15660       # out->is-atom? = true
15661       c7 0/subop/copy *edx 1/imm32/true  # Type-tree-is-atom
15662       {
15663 $parse-type:check-for-type-parameter:
15664         # var tmp/eax: byte = *s->slice
15665         8b/-> *ecx 0/r32/eax
15666         8a/copy-byte *eax 0/r32/AL
15667         81 4/subop/and %eax 0xff/imm32
15668         # if (tmp != '_') break
15669         3d/compare-eax-and 0x5f/imm32/_
15670         75/jump-if-!= break/disp8
15671 $parse-type:type-parameter:
15672         # out->value = type-parameter
15673         c7 0/subop/copy *(edx+4) 0xa/imm32/type-parameter  # Type-tree-value
15674         # out->parameter-name = slice-to-string(ad, s)
15675         8d/copy-address *(edx+8) 0/r32/eax  # Type-tree-parameter-name
15676         (slice-to-string *(ebp+8) %ecx %eax)
15677         e9/jump $parse-type:end/disp32
15678       }
15679 $parse-type:non-type-parameter:
15680       # out->value = pos-or-insert-slice(Type-id, s)
15681       (pos-or-insert-slice Type-id %ecx)  # => eax
15682       89/<- *(edx+4) 0/r32/eax  # Type-tree-value
15683       e9/jump $parse-type:end/disp32
15684     }
15685 $parse-type:non-atom:
15686     # otherwise s == "("
15687     # out->left = parse-type(ad, in)
15688     8d/copy-address *(edx+4) 0/r32/eax  # Type-tree-left
15689     (parse-type *(ebp+8) *(ebp+0xc) %eax *(ebp+0x14) *(ebp+0x18))
15690     # out->right = parse-type-tree(ad, in)
15691     8d/copy-address *(edx+0xc) 0/r32/eax  # Type-tree-right
15692     (parse-type-tree *(ebp+8) *(ebp+0xc) %eax *(ebp+0x14) *(ebp+0x18))
15693 $parse-type:end:
15694     # . reclaim locals
15695     81 0/subop/add %esp 8/imm32
15696     # . restore registers
15697     5a/pop-to-edx
15698     59/pop-to-ecx
15699     58/pop-to-eax
15700     # . epilogue
15701     89/<- %esp 5/r32/ebp
15702     5d/pop-to-ebp
15703     c3/return
15704 
15705 $parse-type:abort:
15706     # error("unexpected token when parsing type: '" s "'\n")
15707     (write-buffered *(ebp+0x14) "unexpected token when parsing type: '")
15708     (write-slice-buffered *(ebp+0x14) %ecx)
15709     (write-buffered *(ebp+0x14) "'\n")
15710     (flush *(ebp+0x14))
15711     (stop *(ebp+0x18) 1)
15712     # never gets here
15713 
15714 parse-type-tree:  # ad: (addr allocation-descriptor), in: (addr stream byte), out: (addr handle type-tree), err: (addr buffered-file), ed: (addr exit-descriptor)
15715     # pseudocode:
15716     #   var tmp: (handle type-tree) = parse-type(ad, in)
15717     #   if tmp == 0
15718     #     return 0
15719     #   out = allocate(Type-tree)
15720     #   out->left = tmp
15721     #   out->right = parse-type-tree(ad, in)
15722     #
15723     # . prologue
15724     55/push-ebp
15725     89/<- %ebp 4/r32/esp
15726     # . save registers
15727     50/push-eax
15728     51/push-ecx
15729     52/push-edx
15730     #
15731     (zero-out *(ebp+0x10) *Handle-size)
15732     # var tmp/ecx: (handle type-tree)
15733     68/push 0/imm32
15734     68/push 0/imm32
15735     89/<- %ecx 4/r32/esp
15736     # tmp = parse-type(ad, in)
15737     (parse-type *(ebp+8) *(ebp+0xc) %ecx *(ebp+0x14) *(ebp+0x18))
15738     # if (tmp == 0) return
15739     81 7/subop/compare *ecx 0/imm32
15740     74/jump-if-= $parse-type-tree:end/disp8
15741     # out = new tree
15742     (allocate *(ebp+8) *Type-tree-size *(ebp+0x10))
15743     # var out-addr/edx: (addr tree) = lookup(*out)
15744     8b/-> *(ebp+0x10) 2/r32/edx
15745     (lookup *edx *(edx+4))  # => eax
15746     89/<- %edx 0/r32/eax
15747     # out->left = tmp
15748     8b/-> *ecx 0/r32/eax
15749     89/<- *(edx+4) 0/r32/eax  # Type-tree-left
15750     8b/-> *(ecx+4) 0/r32/eax
15751     89/<- *(edx+8) 0/r32/eax  # Type-tree-left
15752     # out->right = parse-type-tree(ad, in)
15753     8d/copy-address *(edx+0xc) 0/r32/eax  # Type-tree-right
15754     (parse-type-tree *(ebp+8) *(ebp+0xc) %eax *(ebp+0x14) *(ebp+0x18))
15755 $parse-type-tree:end:
15756     # . reclaim locals
15757     81 0/subop/add %esp 8/imm32
15758     # . restore registers
15759     5a/pop-to-edx
15760     59/pop-to-ecx
15761     58/pop-to-eax
15762     # . epilogue
15763     89/<- %esp 5/r32/ebp
15764     5d/pop-to-ebp
15765     c3/return
15766 
15767 next-mu-token:  # in: (addr stream byte), out: (addr slice)
15768     # pseudocode:
15769     # start:
15770     #   skip-chars-matching-whitespace(in)
15771     #   if in->read >= in->write              # end of in
15772     #     out = {0, 0}
15773     #     return
15774     #   out->start = &in->data[in->read]
15775     #   var curr-byte/eax: byte = in->data[in->read]
15776     #   if curr->byte == ','                  # comment token
15777     #     ++in->read
15778     #     goto start
15779     #   if curr-byte == '#'                   # comment
15780     #     goto done                             # treat as eof
15781     #   if curr-byte == '"'                   # string literal
15782     #     skip-string(in)
15783     #     goto done                           # no metadata
15784     #   if curr-byte == '('
15785     #     ++in->read
15786     #     goto done
15787     #   if curr-byte == ')'
15788     #     ++in->read
15789     #     goto done
15790     #   # read a word
15791     #   while true
15792     #     if in->read >= in->write
15793     #       break
15794     #     curr-byte = in->data[in->read]
15795     #     if curr-byte == ' '
15796     #       break
15797     #     if curr-byte == '\r'
15798     #       break
15799     #     if curr-byte == '\n'
15800     #       break
15801     #     if curr-byte == '('
15802     #       break
15803     #     if curr-byte == ')'
15804     #       break
15805     #     if curr-byte == ','
15806     #       break
15807     #     ++in->read
15808     # done:
15809     #   out->end = &in->data[in->read]
15810     #
15811     # . prologue
15812     55/push-ebp
15813     89/<- %ebp 4/r32/esp
15814     # . save registers
15815     50/push-eax
15816     51/push-ecx
15817     56/push-esi
15818     57/push-edi
15819     # esi = in
15820     8b/-> *(ebp+8) 6/r32/esi
15821     # edi = out
15822     8b/-> *(ebp+0xc) 7/r32/edi
15823 $next-mu-token:start:
15824     (skip-chars-matching-whitespace %esi)
15825 $next-mu-token:check0:
15826     # if (in->read >= in->write) return out = {0, 0}
15827     # . ecx = in->read
15828     8b/-> *(esi+4) 1/r32/ecx
15829     # . if (ecx >= in->write) return out = {0, 0}
15830     3b/compare<- *esi 1/r32/ecx
15831     c7 0/subop/copy *edi 0/imm32
15832     c7 0/subop/copy *(edi+4) 0/imm32
15833     0f 8d/jump-if->= $next-mu-token:end/disp32
15834     # out->start = &in->data[in->read]
15835     8d/copy-address *(esi+ecx+0xc) 0/r32/eax
15836     89/<- *edi 0/r32/eax
15837     # var curr-byte/eax: byte = in->data[in->read]
15838     31/xor-with %eax 0/r32/eax
15839     8a/copy-byte *(esi+ecx+0xc) 0/r32/AL
15840     {
15841 $next-mu-token:check-for-comma:
15842       # if (curr-byte != ',') break
15843       3d/compare-eax-and 0x2c/imm32/comma
15844       75/jump-if-!= break/disp8
15845       # ++in->read
15846       ff 0/subop/increment *(esi+4)
15847       # restart
15848       e9/jump $next-mu-token:start/disp32
15849     }
15850     {
15851 $next-mu-token:check-for-comment:
15852       # if (curr-byte != '#') break
15853       3d/compare-eax-and 0x23/imm32/pound
15854       75/jump-if-!= break/disp8
15855       # return eof
15856       e9/jump $next-mu-token:done/disp32
15857     }
15858     {
15859 $next-mu-token:check-for-string-literal:
15860       # if (curr-byte != '"') break
15861       3d/compare-eax-and 0x22/imm32/dquote
15862       75/jump-if-!= break/disp8
15863       (skip-string %esi)
15864       # return
15865       e9/jump $next-mu-token:done/disp32
15866     }
15867     {
15868 $next-mu-token:check-for-open-paren:
15869       # if (curr-byte != '(') break
15870       3d/compare-eax-and 0x28/imm32/open-paren
15871       75/jump-if-!= break/disp8
15872       # ++in->read
15873       ff 0/subop/increment *(esi+4)
15874       # return
15875       e9/jump $next-mu-token:done/disp32
15876     }
15877     {
15878 $next-mu-token:check-for-close-paren:
15879       # if (curr-byte != ')') break
15880       3d/compare-eax-and 0x29/imm32/close-paren
15881       75/jump-if-!= break/disp8
15882       # ++in->read
15883       ff 0/subop/increment *(esi+4)
15884       # return
15885       e9/jump $next-mu-token:done/disp32
15886     }
15887     {
15888 $next-mu-token:regular-word-without-metadata:
15889       # if (in->read >= in->write) break
15890       # . ecx = in->read
15891       8b/-> *(esi+4) 1/r32/ecx
15892       # . if (ecx >= in->write) break
15893       3b/compare<- *esi 1/r32/ecx
15894       7d/jump-if->= break/disp8
15895       # var c/eax: byte = in->data[in->read]
15896       31/xor-with %eax 0/r32/eax
15897       8a/copy-byte *(esi+ecx+0xc) 0/r32/AL
15898       # if (c == ' ') break
15899       3d/compare-eax-and 0x20/imm32/space
15900       74/jump-if-= break/disp8
15901       # if (c == '\r') break
15902       3d/compare-eax-and 0xd/imm32/carriage-return
15903       74/jump-if-= break/disp8
15904       # if (c == '\n') break
15905       3d/compare-eax-and 0xa/imm32/newline
15906       74/jump-if-= break/disp8
15907       # if (c == '(') break
15908       3d/compare-eax-and 0x28/imm32/open-paren
15909       0f 84/jump-if-= break/disp32
15910       # if (c == ')') break
15911       3d/compare-eax-and 0x29/imm32/close-paren
15912       0f 84/jump-if-= break/disp32
15913       # if (c == ',') break
15914       3d/compare-eax-and 0x2c/imm32/comma
15915       0f 84/jump-if-= break/disp32
15916       # ++in->read
15917       ff 0/subop/increment *(esi+4)
15918       #
15919       e9/jump loop/disp32
15920     }
15921 $next-mu-token:done:
15922     # out->end = &in->data[in->read]
15923     8b/-> *(esi+4) 1/r32/ecx
15924     8d/copy-address *(esi+ecx+0xc) 0/r32/eax
15925     89/<- *(edi+4) 0/r32/eax
15926 $next-mu-token:end:
15927     # . restore registers
15928     5f/pop-to-edi
15929     5e/pop-to-esi
15930     59/pop-to-ecx
15931     58/pop-to-eax
15932     # . epilogue
15933     89/<- %esp 5/r32/ebp
15934     5d/pop-to-ebp
15935     c3/return
15936 
15937 pos-or-insert-slice:  # arr: (addr stream (addr array byte)), s: (addr slice) -> index/eax: int
15938     # . prologue
15939     55/push-ebp
15940     89/<- %ebp 4/r32/esp
15941     # if (pos-slice(arr, s) != -1) return it
15942     (pos-slice *(ebp+8) *(ebp+0xc))  # => eax
15943     3d/compare-eax-and -1/imm32
15944     75/jump-if-!= $pos-or-insert-slice:end/disp8
15945 $pos-or-insert-slice:insert:
15946     # var s2/eax: (handle array byte)
15947     68/push 0/imm32
15948     68/push 0/imm32
15949     89/<- %eax 4/r32/esp
15950     (slice-to-string Heap *(ebp+0xc) %eax)
15951     # throw away alloc-id
15952     (lookup *eax *(eax+4))  # => eax
15953     (write-int *(ebp+8) %eax)
15954     (pos-slice *(ebp+8) *(ebp+0xc))  # => eax
15955 $pos-or-insert-slice:end:
15956     # . reclaim locals
15957     81 0/subop/add %esp 8/imm32
15958     # . epilogue
15959     89/<- %esp 5/r32/ebp
15960     5d/pop-to-ebp
15961     c3/return
15962 
15963 # return the index in an array of strings matching 's', -1 if not found
15964 # index is denominated in elements, not bytes
15965 pos-slice:  # arr: (addr stream (addr array byte)), s: (addr slice) -> index/eax: int
15966     # . prologue
15967     55/push-ebp
15968     89/<- %ebp 4/r32/esp
15969     # . save registers
15970     51/push-ecx
15971     52/push-edx
15972     53/push-ebx
15973     56/push-esi
15974 #?     (write-buffered Stderr "pos-slice: ")
15975 #?     (write-slice-buffered Stderr *(ebp+0xc))
15976 #?     (write-buffered Stderr "\n")
15977 #?     (flush Stderr)
15978     # esi = arr
15979     8b/-> *(ebp+8) 6/r32/esi
15980     # var index/ecx: int = 0
15981     b9/copy-to-ecx 0/imm32
15982     # var curr/edx: (addr (addr array byte)) = arr->data
15983     8d/copy-address *(esi+0xc) 2/r32/edx
15984     # var max/ebx: (addr (addr array byte)) = &arr->data[arr->write]
15985     8b/-> *esi 3/r32/ebx
15986     8d/copy-address *(esi+ebx+0xc) 3/r32/ebx
15987     {
15988 #?       (write-buffered Stderr "  ")
15989 #?       (write-int32-hex-buffered Stderr %ecx)
15990 #?       (write-buffered Stderr "\n")
15991 #?       (flush Stderr)
15992       # if (curr >= max) return -1
15993       39/compare %edx 3/r32/ebx
15994       b8/copy-to-eax -1/imm32
15995       73/jump-if-addr>= $pos-slice:end/disp8
15996       # if (slice-equal?(s, *curr)) break
15997       (slice-equal? *(ebp+0xc) *edx)  # => eax
15998       3d/compare-eax-and 0/imm32/false
15999       75/jump-if-!= break/disp8
16000       # ++index
16001       41/increment-ecx
16002       # curr += 4
16003       81 0/subop/add %edx 4/imm32
16004       #
16005       eb/jump loop/disp8
16006     }
16007     # return index
16008     89/<- %eax 1/r32/ecx
16009 $pos-slice:end:
16010 #?     (write-buffered Stderr "=> ")
16011 #?     (write-int32-hex-buffered Stderr %eax)
16012 #?     (write-buffered Stderr "\n")
16013     # . restore registers
16014     5e/pop-to-esi
16015     5b/pop-to-ebx
16016     5a/pop-to-edx
16017     59/pop-to-ecx
16018     # . epilogue
16019     89/<- %esp 5/r32/ebp
16020     5d/pop-to-ebp
16021     c3/return
16022 
16023 test-parse-var-with-type:
16024     # . prologue
16025     55/push-ebp
16026     89/<- %ebp 4/r32/esp
16027     # setup
16028     8b/-> *Primitive-type-ids 0/r32/eax
16029     89/<- *Type-id 0/r32/eax  # stream-write
16030     # (eax..ecx) = "x:"
16031     b8/copy-to-eax "x:"/imm32
16032     8b/-> *eax 1/r32/ecx
16033     8d/copy-address *(eax+ecx+4) 1/r32/ecx
16034     05/add-to-eax 4/imm32
16035     # var slice/ecx: slice = {eax, ecx}
16036     51/push-ecx
16037     50/push-eax
16038     89/<- %ecx 4/r32/esp
16039     # _test-input-stream contains "int"
16040     (clear-stream _test-input-stream)
16041     (write _test-input-stream "int")
16042     # var v/edx: (handle var)
16043     68/push 0/imm32
16044     68/push 0/imm32
16045     89/<- %edx 4/r32/esp
16046     #
16047     (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0)
16048     # var v-addr/edx: (addr var) = lookup(v)
16049     (lookup *edx *(edx+4))  # => eax
16050     89/<- %edx 0/r32/eax
16051     # check v-addr->name
16052     (lookup *edx *(edx+4))  # Var-name Var-name => eax
16053     (check-strings-equal %eax "x" "F - test-parse-var-with-type/name")
16054     # check v-addr->type
16055     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
16056     (check-ints-equal *eax 1 "F - test-parse-var-with-type/type:0")  # Type-tree-is-atom
16057     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-type/type:1")  # Type-tree-value
16058     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-type/type:2")  # Type-tree-right
16059     # . epilogue
16060     89/<- %esp 5/r32/ebp
16061     5d/pop-to-ebp
16062     c3/return
16063 
16064 test-parse-var-with-type-and-register:
16065     # . prologue
16066     55/push-ebp
16067     89/<- %ebp 4/r32/esp
16068     # setup
16069     8b/-> *Primitive-type-ids 0/r32/eax
16070     89/<- *Type-id 0/r32/eax  # stream-write
16071     # (eax..ecx) = "x/eax:"
16072     b8/copy-to-eax "x/eax:"/imm32
16073     8b/-> *eax 1/r32/ecx
16074     8d/copy-address *(eax+ecx+4) 1/r32/ecx
16075     05/add-to-eax 4/imm32
16076     # var slice/ecx: slice = {eax, ecx}
16077     51/push-ecx
16078     50/push-eax
16079     89/<- %ecx 4/r32/esp
16080     # _test-input-stream contains "int"
16081     (clear-stream _test-input-stream)
16082     (write _test-input-stream "int")
16083     # var v/edx: (handle var)
16084     68/push 0/imm32
16085     68/push 0/imm32
16086     89/<- %edx 4/r32/esp
16087     #
16088     (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0)
16089     # var v-addr/edx: (addr var) = lookup(v)
16090     (lookup *edx *(edx+4))  # => eax
16091     89/<- %edx 0/r32/eax
16092     # check v-addr->name
16093     (lookup *edx *(edx+4))  # Var-name Var-name => eax
16094     (check-strings-equal %eax "x" "F - test-parse-var-with-type-and-register/name")
16095     # check v-addr->register
16096     (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
16097     (check-strings-equal %eax "eax" "F - test-parse-var-with-type-and-register/register")
16098     # check v-addr->type
16099     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
16100     (check-ints-equal *eax 1 "F - test-parse-var-with-type-and-register/type:0")  # Type-tree-is-atom
16101     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-type-and-register/type:1")  # Type-tree-left
16102     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-type-and-register/type:2")  # Type-tree-right
16103     # . epilogue
16104     89/<- %esp 5/r32/ebp
16105     5d/pop-to-ebp
16106     c3/return
16107 
16108 test-parse-var-with-trailing-characters:
16109     # . prologue
16110     55/push-ebp
16111     89/<- %ebp 4/r32/esp
16112     # setup
16113     8b/-> *Primitive-type-ids 0/r32/eax
16114     89/<- *Type-id 0/r32/eax  # stream-write
16115     # (eax..ecx) = "x:"
16116     b8/copy-to-eax "x:"/imm32
16117     8b/-> *eax 1/r32/ecx
16118     8d/copy-address *(eax+ecx+4) 1/r32/ecx
16119     05/add-to-eax 4/imm32
16120     # var slice/ecx: slice = {eax, ecx}
16121     51/push-ecx
16122     50/push-eax
16123     89/<- %ecx 4/r32/esp
16124     # _test-input-stream contains "int,"
16125     (clear-stream _test-input-stream)
16126     (write _test-input-stream "int,")
16127     # var v/edx: (handle var)
16128     68/push 0/imm32
16129     68/push 0/imm32
16130     89/<- %edx 4/r32/esp
16131     #
16132     (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0)
16133     # var v-addr/edx: (addr var) = lookup(v)
16134     (lookup *edx *(edx+4))  # => eax
16135     89/<- %edx 0/r32/eax
16136     # check v-addr->name
16137     (lookup *edx *(edx+4))  # Var-name Var-name => eax
16138     (check-strings-equal %eax "x" "F - test-parse-var-with-trailing-characters/name")
16139     # check v-addr->register
16140     (check-ints-equal *(edx+0x18) 0 "F - test-parse-var-with-trailing-characters/register")  # Var-register
16141     # check v-addr->type
16142     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
16143     (check-ints-equal *eax 1 "F - test-parse-var-with-trailing-characters/type:0")  # Type-tree-is-atom
16144     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-trailing-characters/type:1")  # Type-tree-left
16145     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-trailing-characters/type:1")  # Type-tree-right
16146     # . epilogue
16147     89/<- %esp 5/r32/ebp
16148     5d/pop-to-ebp
16149     c3/return
16150 
16151 test-parse-var-with-register-and-trailing-characters:
16152     # . prologue
16153     55/push-ebp
16154     89/<- %ebp 4/r32/esp
16155     # setup
16156     8b/-> *Primitive-type-ids 0/r32/eax
16157     89/<- *Type-id 0/r32/eax  # stream-write
16158     # (eax..ecx) = "x/eax:"
16159     b8/copy-to-eax "x/eax:"/imm32
16160     8b/-> *eax 1/r32/ecx
16161     8d/copy-address *(eax+ecx+4) 1/r32/ecx
16162     05/add-to-eax 4/imm32
16163     # var slice/ecx: slice = {eax, ecx}
16164     51/push-ecx
16165     50/push-eax
16166     89/<- %ecx 4/r32/esp
16167     # _test-input-stream contains "int,"
16168     (clear-stream _test-input-stream)
16169     (write _test-input-stream "int,")
16170     # var v/edx: (handle var)
16171     68/push 0/imm32
16172     68/push 0/imm32
16173     89/<- %edx 4/r32/esp
16174     #
16175     (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0)
16176     # var v-addr/edx: (addr var) = lookup(v)
16177     (lookup *edx *(edx+4))  # => eax
16178     89/<- %edx 0/r32/eax
16179     # check v-addr->name
16180     (lookup *edx *(edx+4))  # Var-name Var-name => eax
16181     (check-strings-equal %eax "x" "F - test-parse-var-with-register-and-trailing-characters/name")
16182     # check v-addr->register
16183     (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
16184     (check-strings-equal %eax "eax" "F - test-parse-var-with-register-and-trailing-characters/register")
16185     # check v-addr->type
16186     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
16187     (check-ints-equal *eax 1 "F - test-parse-var-with-register-and-trailing-characters/type:0")  # Type-tree-is-atom
16188     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-register-and-trailing-characters/type:1")  # Type-tree-left
16189     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-register-and-trailing-characters/type:2")  # Type-tree-right
16190     # . epilogue
16191     89/<- %esp 5/r32/ebp
16192     5d/pop-to-ebp
16193     c3/return
16194 
16195 test-parse-var-with-compound-type:
16196     # . prologue
16197     55/push-ebp
16198     89/<- %ebp 4/r32/esp
16199     # setup
16200     8b/-> *Primitive-type-ids 0/r32/eax
16201     89/<- *Type-id 0/r32/eax  # stream-write
16202     # (eax..ecx) = "x:"
16203     b8/copy-to-eax "x:"/imm32
16204     8b/-> *eax 1/r32/ecx
16205     8d/copy-address *(eax+ecx+4) 1/r32/ecx
16206     05/add-to-eax 4/imm32
16207     # var slice/ecx: slice = {eax, ecx}
16208     51/push-ecx
16209     50/push-eax
16210     89/<- %ecx 4/r32/esp
16211     # _test-input-stream contains "(addr int)"
16212     (clear-stream _test-input-stream)
16213     (write _test-input-stream "(addr int)")
16214     # var v/edx: (handle var)
16215     68/push 0/imm32
16216     68/push 0/imm32
16217     89/<- %edx 4/r32/esp
16218     #
16219     (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0)
16220     # var v-addr/edx: (addr var) = lookup(v)
16221     (lookup *edx *(edx+4))  # => eax
16222     89/<- %edx 0/r32/eax
16223     # check v-addr->name
16224     (lookup *edx *(edx+4))  # Var-name Var-name => eax
16225     (check-strings-equal %eax "x" "F - test-parse-var-with-compound-type/name")
16226     # check v-addr->register
16227     (check-ints-equal *(edx+0x18) 0 "F - test-parse-var-with-compound-type/register")  # Var-register
16228     # - check v-addr->type
16229     # var type/edx: (addr type-tree) = var->type
16230     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
16231     89/<- %edx 0/r32/eax
16232     # type is a non-atom
16233     (check-ints-equal *edx 0 "F - test-parse-var-with-compound-type/type:0")  # Type-tree-is-atom
16234     # type->left == atom(addr)
16235     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
16236     (check-ints-equal *eax 1 "F - test-parse-var-with-compound-type/type:1")  # Type-tree-is-atom
16237     (check-ints-equal *(eax+4) 2 "F - test-parse-var-with-compound-type/type:2")  # Type-tree-value
16238     # type->right->left == atom(int)
16239     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
16240     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
16241     (check-ints-equal *eax 1 "F - test-parse-var-with-compound-type/type:3")  # Type-tree-is-atom
16242     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-compound-type/type:4")  # Type-tree-value
16243     # type->right->right == null
16244     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-compound-type/type:5")  # Type-tree-right
16245     # . epilogue
16246     89/<- %esp 5/r32/ebp
16247     5d/pop-to-ebp
16248     c3/return
16249 
16250 # identifier starts with a letter or '$' or '_'
16251 # no constraints at the moment on later letters
16252 # all we really want to do so far is exclude '{', '}' and '->'
16253 is-identifier?:  # in: (addr slice) -> result/eax: boolean
16254     # . prologue
16255     55/push-ebp
16256     89/<- %ebp 4/r32/esp
16257     # if (slice-empty?(in)) return false
16258     (slice-empty? *(ebp+8))  # => eax
16259     3d/compare-eax-and 0/imm32/false
16260     75/jump-if-!= $is-identifier?:false/disp8
16261     # var c/eax: byte = *in->start
16262     8b/-> *(ebp+8) 0/r32/eax
16263     8b/-> *eax 0/r32/eax
16264     8a/copy-byte *eax 0/r32/AL
16265     81 4/subop/and %eax 0xff/imm32
16266     # if (c == '$') return true
16267     3d/compare-eax-and 0x24/imm32/$
16268     74/jump-if-= $is-identifier?:true/disp8
16269     # if (c == '_') return true
16270     3d/compare-eax-and 0x5f/imm32/_
16271     74/jump-if-= $is-identifier?:true/disp8
16272     # drop case
16273     25/and-eax-with 0x5f/imm32
16274     # if (c < 'A') return false
16275     3d/compare-eax-and 0x41/imm32/A
16276     7c/jump-if-< $is-identifier?:false/disp8
16277     # if (c > 'Z') return false
16278     3d/compare-eax-and 0x5a/imm32/Z
16279     7f/jump-if-> $is-identifier?:false/disp8
16280     # otherwise return true
16281 $is-identifier?:true:
16282     b8/copy-to-eax 1/imm32/true
16283     eb/jump $is-identifier?:end/disp8
16284 $is-identifier?:false:
16285     b8/copy-to-eax 0/imm32/false
16286 $is-identifier?:end:
16287     # . epilogue
16288     89/<- %esp 5/r32/ebp
16289     5d/pop-to-ebp
16290     c3/return
16291 
16292 test-is-identifier-dollar:
16293     # . prologue
16294     55/push-ebp
16295     89/<- %ebp 4/r32/esp
16296     # (eax..ecx) = "$a"
16297     b8/copy-to-eax "$a"/imm32
16298     8b/-> *eax 1/r32/ecx
16299     8d/copy-address *(eax+ecx+4) 1/r32/ecx
16300     05/add-to-eax 4/imm32
16301     # var slice/ecx: slice = {eax, ecx}
16302     51/push-ecx
16303     50/push-eax
16304     89/<- %ecx 4/r32/esp
16305     #
16306     (is-identifier? %ecx)
16307     (check-ints-equal %eax 1 "F - test-is-identifier-dollar")
16308     # . epilogue
16309     89/<- %esp 5/r32/ebp
16310     5d/pop-to-ebp
16311     c3/return
16312 
16313 test-is-identifier-underscore:
16314     # . prologue
16315     55/push-ebp
16316     89/<- %ebp 4/r32/esp
16317     # (eax..ecx) = "_a"
16318     b8/copy-to-eax "_a"/imm32
16319     8b/-> *eax 1/r32/ecx
16320     8d/copy-address *(eax+ecx+4) 1/r32/ecx
16321     05/add-to-eax 4/imm32
16322     # var slice/ecx: slice = {eax, ecx}
16323     51/push-ecx
16324     50/push-eax
16325     89/<- %ecx 4/r32/esp
16326     #
16327     (is-identifier? %ecx)
16328     (check-ints-equal %eax 1 "F - test-is-identifier-underscore")
16329     # . epilogue
16330     89/<- %esp 5/r32/ebp
16331     5d/pop-to-ebp
16332     c3/return
16333 
16334 test-is-identifier-a:
16335     # . prologue
16336     55/push-ebp
16337     89/<- %ebp 4/r32/esp
16338     # (eax..ecx) = "a$"
16339     b8/copy-to-eax "a$"/imm32
16340     8b/-> *eax 1/r32/ecx
16341     8d/copy-address *(eax+ecx+4) 1/r32/ecx
16342     05/add-to-eax 4/imm32
16343     # var slice/ecx: slice = {eax, ecx}
16344     51/push-ecx
16345     50/push-eax
16346     89/<- %ecx 4/r32/esp
16347     #
16348     (is-identifier? %ecx)
16349     (check-ints-equal %eax 1 "F - test-is-identifier-a")
16350     # . epilogue
16351     89/<- %esp 5/r32/ebp
16352     5d/pop-to-ebp
16353     c3/return
16354 
16355 test-is-identifier-z:
16356     # . prologue
16357     55/push-ebp
16358     89/<- %ebp 4/r32/esp
16359     # (eax..ecx) = "z$"
16360     b8/copy-to-eax "z$"/imm32
16361     8b/-> *eax 1/r32/ecx
16362     8d/copy-address *(eax+ecx+4) 1/r32/ecx
16363     05/add-to-eax 4/imm32
16364     # var slice/ecx: slice = {eax, ecx}
16365     51/push-ecx
16366     50/push-eax
16367     89/<- %ecx 4/r32/esp
16368     #
16369     (is-identifier? %ecx)
16370     (check-ints-equal %eax 1 "F - test-is-identifier-z")
16371     # . epilogue
16372     89/<- %esp 5/r32/ebp
16373     5d/pop-to-ebp
16374     c3/return
16375 
16376 test-is-identifier-A:
16377     # . prologue
16378     55/push-ebp
16379     89/<- %ebp 4/r32/esp
16380     # (eax..ecx) = "A$"
16381     b8/copy-to-eax "A$"/imm32
16382     8b/-> *eax 1/r32/ecx
16383     8d/copy-address *(eax+ecx+4) 1/r32/ecx
16384     05/add-to-eax 4/imm32
16385     # var slice/ecx: slice = {eax, ecx}
16386     51/push-ecx
16387     50/push-eax
16388     89/<- %ecx 4/r32/esp
16389     #
16390     (is-identifier? %ecx)
16391     (check-ints-equal %eax 1 "F - test-is-identifier-A")
16392     # . epilogue
16393     89/<- %esp 5/r32/ebp
16394     5d/pop-to-ebp
16395     c3/return
16396 
16397 test-is-identifier-Z:
16398     # . prologue
16399     55/push-ebp
16400     89/<- %ebp 4/r32/esp
16401     # (eax..ecx) = "Z$"
16402     b8/copy-to-eax "Z$"/imm32
16403     8b/-> *eax 1/r32/ecx
16404     8d/copy-address *(eax+ecx+4) 1/r32/ecx
16405     05/add-to-eax 4/imm32
16406     # var slice/ecx: slice = {eax, ecx}
16407     51/push-ecx
16408     50/push-eax
16409     89/<- %ecx 4/r32/esp
16410     #
16411     (is-identifier? %ecx)
16412     (check-ints-equal %eax 1 "F - test-is-identifier-Z")
16413     # . epilogue
16414     89/<- %esp 5/r32/ebp
16415     5d/pop-to-ebp
16416     c3/return
16417 
16418 test-is-identifier-at:
16419     # character before 'A' is invalid
16420     # . prologue
16421     55/push-ebp
16422     89/<- %ebp 4/r32/esp
16423     # (eax..ecx) = "@a"
16424     b8/copy-to-eax "@a"/imm32
16425     8b/-> *eax 1/r32/ecx
16426     8d/copy-address *(eax+ecx+4) 1/r32/ecx
16427     05/add-to-eax 4/imm32
16428     # var slice/ecx: slice = {eax, ecx}
16429     51/push-ecx
16430     50/push-eax
16431     89/<- %ecx 4/r32/esp
16432     #
16433     (is-identifier? %ecx)
16434     (check-ints-equal %eax 0 "F - test-is-identifier-@")
16435     # . epilogue
16436     89/<- %esp 5/r32/ebp
16437     5d/pop-to-ebp
16438     c3/return
16439 
16440 test-is-identifier-square-bracket:
16441     # character after 'Z' is invalid
16442     # . prologue
16443     55/push-ebp
16444     89/<- %ebp 4/r32/esp
16445     # (eax..ecx) = "[a"
16446     b8/copy-to-eax "[a"/imm32
16447     8b/-> *eax 1/r32/ecx
16448     8d/copy-address *(eax+ecx+4) 1/r32/ecx
16449     05/add-to-eax 4/imm32
16450     # var slice/ecx: slice = {eax, ecx}
16451     51/push-ecx
16452     50/push-eax
16453     89/<- %ecx 4/r32/esp
16454     #
16455     (is-identifier? %ecx)
16456     (check-ints-equal %eax 0 "F - test-is-identifier-@")
16457     # . epilogue
16458     89/<- %esp 5/r32/ebp
16459     5d/pop-to-ebp
16460     c3/return
16461 
16462 test-is-identifier-backtick:
16463     # character before 'a' is invalid
16464     # . prologue
16465     55/push-ebp
16466     89/<- %ebp 4/r32/esp
16467     # (eax..ecx) = "`a"
16468     b8/copy-to-eax "`a"/imm32
16469     8b/-> *eax 1/r32/ecx
16470     8d/copy-address *(eax+ecx+4) 1/r32/ecx
16471     05/add-to-eax 4/imm32
16472     # var slice/ecx: slice = {eax, ecx}
16473     51/push-ecx
16474     50/push-eax
16475     89/<- %ecx 4/r32/esp
16476     #
16477     (is-identifier? %ecx)
16478     (check-ints-equal %eax 0 "F - test-is-identifier-backtick")
16479     # . epilogue
16480     89/<- %esp 5/r32/ebp
16481     5d/pop-to-ebp
16482     c3/return
16483 
16484 test-is-identifier-curly-brace-open:
16485     # character after 'z' is invalid; also used for blocks
16486     # . prologue
16487     55/push-ebp
16488     89/<- %ebp 4/r32/esp
16489     # (eax..ecx) = "{a"
16490     b8/copy-to-eax "{a"/imm32
16491     8b/-> *eax 1/r32/ecx
16492     8d/copy-address *(eax+ecx+4) 1/r32/ecx
16493     05/add-to-eax 4/imm32
16494     # var slice/ecx: slice = {eax, ecx}
16495     51/push-ecx
16496     50/push-eax
16497     89/<- %ecx 4/r32/esp
16498     #
16499     (is-identifier? %ecx)
16500     (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-open")
16501     # . epilogue
16502     89/<- %esp 5/r32/ebp
16503     5d/pop-to-ebp
16504     c3/return
16505 
16506 test-is-identifier-curly-brace-close:
16507     # . prologue
16508     55/push-ebp
16509     89/<- %ebp 4/r32/esp
16510     # (eax..ecx) = "}a"
16511     b8/copy-to-eax "}a"/imm32
16512     8b/-> *eax 1/r32/ecx
16513     8d/copy-address *(eax+ecx+4) 1/r32/ecx
16514     05/add-to-eax 4/imm32
16515     # var slice/ecx: slice = {eax, ecx}
16516     51/push-ecx
16517     50/push-eax
16518     89/<- %ecx 4/r32/esp
16519     #
16520     (is-identifier? %ecx)
16521     (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-close")
16522     # . epilogue
16523     89/<- %esp 5/r32/ebp
16524     5d/pop-to-ebp
16525     c3/return
16526 
16527 test-is-identifier-hyphen:
16528     # disallow leading '-' since '->' has special meaning
16529     # . prologue
16530     55/push-ebp
16531     89/<- %ebp 4/r32/esp
16532     # (eax..ecx) = "-a"
16533     b8/copy-to-eax "-a"/imm32
16534     8b/-> *eax 1/r32/ecx
16535     8d/copy-address *(eax+ecx+4) 1/r32/ecx
16536     05/add-to-eax 4/imm32
16537     # var slice/ecx: slice = {eax, ecx}
16538     51/push-ecx
16539     50/push-eax
16540     89/<- %ecx 4/r32/esp
16541     #
16542     (is-identifier? %ecx)
16543     (check-ints-equal %eax 0 "F - test-is-identifier-hyphen")
16544     # . epilogue
16545     89/<- %esp 5/r32/ebp
16546     5d/pop-to-ebp
16547     c3/return
16548 
16549 populate-mu-function-body:  # in: (addr buffered-file), out: (addr function), vars: (addr stack live-var), err: (addr buffered-file), ed: (addr exit-descriptor)
16550     # . prologue
16551     55/push-ebp
16552     89/<- %ebp 4/r32/esp
16553     # . save registers
16554     50/push-eax
16555     56/push-esi
16556     57/push-edi
16557     # esi = in
16558     8b/-> *(ebp+8) 6/r32/esi
16559     # edi = out
16560     8b/-> *(ebp+0xc) 7/r32/edi
16561     # initialize some global state
16562     c7 0/subop/copy *Curr-block-depth 1/imm32
16563     # parse-mu-block(in, vars, out, out->body)
16564     8d/copy-address *(edi+0x18) 0/r32/eax  # Function-body
16565     (parse-mu-block %esi *(ebp+0x10) %edi %eax *(ebp+0x14) *(ebp+0x18))
16566 $populate-mu-function-body:end:
16567     # . restore registers
16568     5f/pop-to-edi
16569     5e/pop-to-esi
16570     58/pop-to-eax
16571     # . epilogue
16572     89/<- %esp 5/r32/ebp
16573     5d/pop-to-ebp
16574     c3/return
16575 
16576 # parses a block, assuming that the leading '{' has already been read by the caller
16577 parse-mu-block:  # in: (addr buffered-file), vars: (addr stack live-var), fn: (addr function), out: (addr handle block), err: (addr buffered-file), ed: (addr exit-descriptor)
16578     # pseudocode:
16579     #   var line: (stream byte 512)
16580     #   var word-slice: slice
16581     #   allocate(Heap, Stmt-size, out)
16582     #   var out-addr: (addr block) = lookup(*out)
16583     #   out-addr->tag = 0/block
16584     #   out-addr->var = some unique name
16585     #   push(vars, {out-addr->var, false})
16586     #   while true                                  # line loop
16587     #     clear-stream(line)
16588     #     read-line-buffered(in, line)
16589     #     if (line->write == 0) break               # end of file
16590     #     word-slice = next-mu-token(line)
16591     #     if slice-empty?(word-slice)               # end of line
16592     #       continue
16593     #     else if slice-starts-with?(word-slice, "#")
16594     #       continue
16595     #     else if slice-equal?(word-slice, "{")
16596     #       assert(no-tokens-in(line))
16597     #       block = parse-mu-block(in, vars, fn)
16598     #       append-to-block(out-addr, block)
16599     #     else if slice-equal?(word-slice, "}")
16600     #       break
16601     #     else if slice-ends-with?(word-slice, ":")
16602     #       # TODO: error-check the rest of 'line'
16603     #       --word-slice->end to skip ':'
16604     #       named-block = parse-mu-named-block(word-slice, in, vars, fn)
16605     #       append-to-block(out-addr, named-block)
16606     #     else if slice-equal?(word-slice, "var")
16607     #       var-def = parse-mu-var-def(line, vars, fn)
16608     #       append-to-block(out-addr, var-def)
16609     #     else
16610     #       stmt = parse-mu-stmt(line, vars, fn)
16611     #       append-to-block(out-addr, stmt)
16612     #   pop(vars)
16613     #
16614     # . prologue
16615     55/push-ebp
16616     89/<- %ebp 4/r32/esp
16617     # . save registers
16618     50/push-eax
16619     51/push-ecx
16620     52/push-edx
16621     53/push-ebx
16622     57/push-edi
16623     # var line/ecx: (stream byte 512)
16624     81 5/subop/subtract %esp 0x200/imm32
16625     68/push 0x200/imm32/size
16626     68/push 0/imm32/read
16627     68/push 0/imm32/write
16628     89/<- %ecx 4/r32/esp
16629     # var word-slice/edx: slice
16630     68/push 0/imm32/end
16631     68/push 0/imm32/start
16632     89/<- %edx 4/r32/esp
16633     # allocate into out
16634     (allocate Heap *Stmt-size *(ebp+0x14))
16635     # var out-addr/edi: (addr block) = lookup(*out)
16636     8b/-> *(ebp+0x14) 7/r32/edi
16637     (lookup *edi *(edi+4))  # => eax
16638     89/<- %edi 0/r32/eax
16639     # out-addr->tag is 0 (block) by default
16640     # set out-addr->var
16641     8d/copy-address *(edi+0xc) 0/r32/eax  # Block-var
16642     (new-block-name *(ebp+0x10) %eax)
16643     # push(vars, out-addr->var)
16644     (push *(ebp+0xc) *(edi+0xc))  # Block-var
16645     (push *(ebp+0xc) *(edi+0x10))  # Block-var
16646     (push *(ebp+0xc) 0)  # false
16647     # increment *Curr-block-depth
16648     ff 0/subop/increment *Curr-block-depth
16649     {
16650 $parse-mu-block:line-loop:
16651       # line = read-line-buffered(in)
16652       (clear-stream %ecx)
16653       (read-line-buffered *(ebp+8) %ecx)
16654 #?       (write-buffered Stderr "line: ")
16655 #?       (write-stream-data Stderr %ecx)
16656 #? #?       (write-buffered Stderr Newline)  # line has its own newline
16657 #?       (flush Stderr)
16658 #?       (rewind-stream %ecx)
16659       # if (line->write == 0) break
16660       81 7/subop/compare *ecx 0/imm32
16661       0f 84/jump-if-= break/disp32
16662 #?       (write-buffered Stderr "vars:\n")
16663 #?       (dump-vars *(ebp+0xc))
16664       # word-slice = next-mu-token(line)
16665       (next-mu-token %ecx %edx)
16666 #?       (write-buffered Stderr "word: ")
16667 #?       (write-slice-buffered Stderr %edx)
16668 #?       (write-buffered Stderr Newline)
16669 #?       (flush Stderr)
16670       # if slice-empty?(word-slice) continue
16671       (slice-empty? %edx)
16672       3d/compare-eax-and 0/imm32/false
16673       0f 85/jump-if-!= loop/disp32
16674       # if (slice-starts-with?(word-slice, '#') continue
16675       # . eax = *word-slice->start
16676       8b/-> *edx 0/r32/eax
16677       8a/copy-byte *eax 0/r32/AL
16678       81 4/subop/and %eax 0xff/imm32
16679       # . if (eax == '#') continue
16680       3d/compare-eax-and 0x23/imm32/hash
16681       0f 84/jump-if-= loop/disp32
16682       # if slice-equal?(word-slice, "{")
16683       {
16684 $parse-mu-block:check-for-block:
16685         (slice-equal? %edx "{")
16686         3d/compare-eax-and 0/imm32/false
16687         74/jump-if-= break/disp8
16688         (check-no-tokens-left %ecx)
16689         # parse new block and append
16690         # . var tmp/eax: (handle block)
16691         68/push 0/imm32
16692         68/push 0/imm32
16693         89/<- %eax 4/r32/esp
16694         # .
16695         (parse-mu-block *(ebp+8) *(ebp+0xc) *(ebp+0x10) %eax *(ebp+0x18) *(ebp+0x1c))
16696         (append-to-block Heap %edi  *eax *(eax+4))
16697         # . reclaim tmp
16698         81 0/subop/add %esp 8/imm32
16699         # .
16700         e9/jump $parse-mu-block:line-loop/disp32
16701       }
16702       # if slice-equal?(word-slice, "}") break
16703 $parse-mu-block:check-for-end:
16704       (slice-equal? %edx "}")
16705       3d/compare-eax-and 0/imm32/false
16706       0f 85/jump-if-!= break/disp32
16707       # if slice-ends-with?(word-slice, ":") parse named block and append
16708       {
16709 $parse-mu-block:check-for-named-block:
16710         # . eax = *(word-slice->end-1)
16711         8b/-> *(edx+4) 0/r32/eax
16712         48/decrement-eax
16713         8a/copy-byte *eax 0/r32/AL
16714         81 4/subop/and %eax 0xff/imm32
16715         # . if (eax != ':') break
16716         3d/compare-eax-and 0x3a/imm32/colon
16717         0f 85/jump-if-!= break/disp32
16718         # TODO: error-check the rest of 'line'
16719         #
16720         # skip ':'
16721         ff 1/subop/decrement *(edx+4)  # Slice-end
16722         # var tmp/eax: (handle block)
16723         68/push 0/imm32
16724         68/push 0/imm32
16725         89/<- %eax 4/r32/esp
16726         #
16727         (parse-mu-named-block %edx *(ebp+8) *(ebp+0xc) *(ebp+0x10) %eax *(ebp+0x18) *(ebp+0x1c))
16728         (append-to-block Heap %edi  *eax *(eax+4))
16729         # reclaim tmp
16730         81 0/subop/add %esp 8/imm32
16731         #
16732         e9/jump $parse-mu-block:line-loop/disp32
16733       }
16734       # if slice-equal?(word-slice, "var")
16735       {
16736 $parse-mu-block:check-for-var:
16737         (slice-equal? %edx "var")
16738         3d/compare-eax-and 0/imm32/false
16739         74/jump-if-= break/disp8
16740         # var tmp/eax: (handle block)
16741         68/push 0/imm32
16742         68/push 0/imm32
16743         89/<- %eax 4/r32/esp
16744         #
16745         (parse-mu-var-def %ecx *(ebp+0xc) %eax *(ebp+0x10) *(ebp+0x18) *(ebp+0x1c))
16746         (append-to-block Heap %edi  *eax *(eax+4))
16747         # reclaim tmp
16748         81 0/subop/add %esp 8/imm32
16749         #
16750         e9/jump $parse-mu-block:line-loop/disp32
16751       }
16752 $parse-mu-block:regular-stmt:
16753       # otherwise
16754       # var tmp/eax: (handle block)
16755       68/push 0/imm32
16756       68/push 0/imm32
16757       89/<- %eax 4/r32/esp
16758       #
16759       (parse-mu-stmt %ecx *(ebp+0xc) *(ebp+0x10) %eax *(ebp+0x18) *(ebp+0x1c))
16760       (append-to-block Heap %edi  *eax *(eax+4))
16761       # reclaim tmp
16762       81 0/subop/add %esp 8/imm32
16763       #
16764       e9/jump loop/disp32
16765     } # end line loop
16766     (clean-up-blocks *(ebp+0xc) *Curr-block-depth *(ebp+0x10))
16767     # decrement *Curr-block-depth
16768     ff 1/subop/decrement *Curr-block-depth
16769     # pop(vars)
16770     (pop *(ebp+0xc))  # => eax
16771     (pop *(ebp+0xc))  # => eax
16772     (pop *(ebp+0xc))  # => eax
16773 $parse-mu-block:end:
16774     # . reclaim locals
16775     81 0/subop/add %esp 0x214/imm32
16776     # . restore registers
16777     5f/pop-to-edi
16778     5b/pop-to-ebx
16779     5a/pop-to-edx
16780     59/pop-to-ecx
16781     58/pop-to-eax
16782     # . epilogue
16783     89/<- %esp 5/r32/ebp
16784     5d/pop-to-ebp
16785     c3/return
16786 
16787 $parse-mu-block:abort:
16788     # error("'{' or '}' should be on its own line, but got '")
16789     (write-buffered *(ebp+0x18) "'{' or '}' should be on its own line, but got '")
16790     (rewind-stream %ecx)
16791     (write-stream-data *(ebp+0x18) %ecx)
16792     (write-buffered *(ebp+0x18) "'\n")
16793     (flush *(ebp+0x18))
16794     (stop *(ebp+0x1c) 1)
16795     # never gets here
16796 
16797 new-block-name:  # fn: (addr function), out: (addr handle var)
16798     # . prologue
16799     55/push-ebp
16800     89/<- %ebp 4/r32/esp
16801     # . save registers
16802     50/push-eax
16803     51/push-ecx
16804     52/push-edx
16805     # var n/ecx: int = len(fn->name) + 10 for an int + 2 for '$:'
16806     8b/-> *(ebp+8) 0/r32/eax
16807     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16808     8b/-> *eax 0/r32/eax  # String-size
16809     05/add-to-eax 0xd/imm32  # 10 + 2 for '$:'
16810     89/<- %ecx 0/r32/eax
16811     # var name/edx: (stream byte n)
16812     29/subtract-from %esp 1/r32/ecx
16813     ff 6/subop/push %ecx
16814     68/push 0/imm32/read
16815     68/push 0/imm32/write
16816     89/<- %edx 4/r32/esp
16817     (clear-stream %edx)
16818     # eax = fn->name
16819     8b/-> *(ebp+8) 0/r32/eax
16820     (lookup *eax *(eax+4))  # Function-name Function-name => eax
16821     # construct result using Next-block-index (and increment it)
16822     (write %edx "$")
16823     (write %edx %eax)
16824     (write %edx ":")
16825     (write-int32-hex %edx *Next-block-index)
16826     ff 0/subop/increment *Next-block-index
16827     # var s/eax: slice = {name->data, name->data + name->write}  (clobbering edx)
16828     # . eax = name->write
16829     8b/-> *edx 0/r32/eax
16830     # . edx = name->data
16831     8d/copy-address *(edx+0xc) 2/r32/edx
16832     # . eax = name->write + name->data
16833     01/add-to %eax 2/r32/edx
16834     # . push {edx, eax}
16835     ff 6/subop/push %eax
16836     ff 6/subop/push %edx
16837     89/<- %eax 4/r32/esp
16838     # out = new literal(s)
16839     (new-literal Heap %eax *(ebp+0xc))
16840 #?     8b/-> *(ebp+0xc) 0/r32/eax
16841 #?     (write-buffered Stderr "type allocid in caller after new-literal: ")
16842 #?     (write-int32-hex-buffered Stderr *(eax+8))
16843 #?     (write-buffered Stderr " for var ")
16844 #?     (write-int32-hex-buffered Stderr %eax)
16845 #?     (write-buffered Stderr Newline)
16846 #?     (flush Stderr)
16847 $new-block-name:end:
16848     # . reclaim locals
16849     81 0/subop/add %ecx 0xc/imm32  # name.{read/write/len}
16850     81 0/subop/add %ecx 8/imm32  # slice
16851     01/add-to %esp 1/r32/ecx
16852     # . restore registers
16853     5a/pop-to-edx
16854     59/pop-to-ecx
16855     58/pop-to-eax
16856     # . epilogue
16857     89/<- %esp 5/r32/ebp
16858     5d/pop-to-ebp
16859     c3/return
16860 
16861 check-no-tokens-left:  # line: (addr stream byte)
16862     # . prologue
16863     55/push-ebp
16864     89/<- %ebp 4/r32/esp
16865     # . save registers
16866     50/push-eax
16867     51/push-ecx
16868     # var s/ecx: slice
16869     68/push 0/imm32/end
16870     68/push 0/imm32/start
16871     89/<- %ecx 4/r32/esp
16872     #
16873     (next-mu-token *(ebp+8) %ecx)
16874     # if slice-empty?(s) return
16875     (slice-empty? %ecx)
16876     3d/compare-eax-and 0/imm32/false
16877     75/jump-if-!= $check-no-tokens-left:end/disp8
16878     # if (slice-starts-with?(s, '#') return
16879     # . eax = *s->start
16880     8b/-> *edx 0/r32/eax
16881     8a/copy-byte *eax 0/r32/AL
16882     81 4/subop/and %eax 0xff/imm32
16883     # . if (eax == '#') continue
16884     3d/compare-eax-and 0x23/imm32/hash
16885     74/jump-if-= $check-no-tokens-left:end/disp8
16886     # abort
16887     (write-buffered Stderr "'{' or '}' should be on its own line, but got '")
16888     (rewind-stream %ecx)
16889     (write-stream 2 %ecx)
16890     (write-buffered Stderr "'\n")
16891     (flush Stderr)
16892     # . syscall(exit, 1)
16893     bb/copy-to-ebx  1/imm32
16894     e8/call syscall_exit/disp32
16895     # never gets here
16896 $check-no-tokens-left:end:
16897     # . reclaim locals
16898     81 0/subop/add %esp 8/imm32
16899     # . restore registers
16900     59/pop-to-ecx
16901     58/pop-to-eax
16902     # . epilogue
16903     89/<- %esp 5/r32/ebp
16904     5d/pop-to-ebp
16905     c3/return
16906 
16907 parse-mu-named-block:  # name: (addr slice), in: (addr buffered-file), vars: (addr stack live-var), fn: (addr function), out: (addr handle stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
16908     # pseudocode:
16909     #   var v: (handle var)
16910     #   new-literal(name, v)
16911     #   push(vars, {v, false})
16912     #   parse-mu-block(in, vars, fn, out)
16913     #   pop(vars)
16914     #   out->tag = block
16915     #   out->var = v
16916     #
16917     # . prologue
16918     55/push-ebp
16919     89/<- %ebp 4/r32/esp
16920     # . save registers
16921     50/push-eax
16922     51/push-ecx
16923     57/push-edi
16924     # var v/ecx: (handle var)
16925     68/push 0/imm32
16926     68/push 0/imm32
16927     89/<- %ecx 4/r32/esp
16928     #
16929     (new-literal Heap *(ebp+8) %ecx)
16930     # push(vars, v)
16931     (push *(ebp+0x10) *ecx)
16932     (push *(ebp+0x10) *(ecx+4))
16933     (push *(ebp+0x10) 0)  # false
16934     #
16935     (parse-mu-block *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c) *(ebp+0x20))
16936     # pop v off vars
16937     (pop *(ebp+0x10))  # => eax
16938     (pop *(ebp+0x10))  # => eax
16939     (pop *(ebp+0x10))  # => eax
16940     # var out-addr/edi: (addr stmt) = lookup(*out)
16941     8b/-> *(ebp+0x18) 7/r32/edi
16942     (lookup *edi *(edi+4))  # => eax
16943     89/<- %edi 0/r32/eax
16944     # out-addr->tag = named-block
16945     c7 0/subop/copy *edi 0/imm32/block  # Stmt-tag
16946     # out-addr->var = v
16947     8b/-> *ecx 0/r32/eax
16948     89/<- *(edi+0xc) 0/r32/eax  # Block-var
16949     8b/-> *(ecx+4) 0/r32/eax
16950     89/<- *(edi+0x10) 0/r32/eax  # Block-var
16951 $parse-mu-named-block:end:
16952     # . reclaim locals
16953     81 0/subop/add %esp 8/imm32
16954     # . restore registers
16955     5f/pop-to-edi
16956     59/pop-to-ecx
16957     58/pop-to-eax
16958     # . epilogue
16959     89/<- %esp 5/r32/ebp
16960     5d/pop-to-ebp
16961     c3/return
16962 
16963 parse-mu-var-def:  # line: (addr stream byte), vars: (addr stack live-var), out: (addr handle stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
16964     # . prologue
16965     55/push-ebp
16966     89/<- %ebp 4/r32/esp
16967     # . save registers
16968     50/push-eax
16969     51/push-ecx
16970     52/push-edx
16971     56/push-esi
16972     57/push-edi
16973     # edi = out
16974     8b/-> *(ebp+0x10) 7/r32/edi
16975     # var word-slice/ecx: slice
16976     68/push 0/imm32/end
16977     68/push 0/imm32/start
16978     89/<- %ecx 4/r32/esp
16979     # var v/edx: (handle var)
16980     68/push 0/imm32
16981     68/push 0/imm32
16982     89/<- %edx 4/r32/esp
16983     # v = parse-var-with-type(next-mu-token(line))
16984     (next-mu-token *(ebp+8) %ecx)
16985     {
16986       # just for tests, support null fn
16987       8b/-> *(ebp+0x14) 0/r32/eax
16988       3d/compare-eax-and 0/imm32
16989       74/jump-if-= break/disp8
16990       (lookup *eax *(eax+4))  # Var-name Var-name => eax
16991     }
16992     (parse-var-with-type %ecx *(ebp+8) %edx %eax *(ebp+0x18) *(ebp+0x1c))
16993     # var v-addr/esi: (addr var)
16994     (lookup *edx *(edx+4))  # => eax
16995     89/<- %esi 0/r32/eax
16996     # v->block-depth = *Curr-block-depth
16997     8b/-> *Curr-block-depth 0/r32/eax
16998     89/<- *(esi+0x10) 0/r32/eax  # Var-block-depth
16999     # either v has no register and there's no more to this line
17000     81 7/subop/compare *(esi+0x18) 0/imm32
17001     {
17002       75/jump-if-!= break/disp8
17003       # if v-addr->type == byte, abort
17004       (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
17005       (is-simple-mu-type? %eax 8)  # byte => eax
17006       3d/compare-eax-and 0/imm32/false
17007       0f 85/jump-if-!= $parse-mu-var-def:error-byte-on-stack/disp32
17008       # ensure that there's nothing else on this line
17009       (next-mu-token *(ebp+8) %ecx)
17010       (slice-empty? %ecx)  # => eax
17011       3d/compare-eax-and 0/imm32/false
17012       0f 84/jump-if-= $parse-mu-var-def:error2/disp32
17013       #
17014       (new-var-def Heap  *edx *(edx+4)  %edi)
17015       e9/jump $parse-mu-var-def:update-vars/disp32
17016     }
17017     # or v has a register and there's more to this line
17018     {
17019       0f 84/jump-if-= break/disp32
17020       # if v-addr->type == byte, check for unsupported registers
17021       {
17022         (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
17023         (is-simple-mu-type? %eax 8)  # byte => eax
17024         3d/compare-eax-and 0/imm32/false
17025         74/jump-if-= break/disp8
17026         (lookup *(esi+0x18) *(esi+0x1c))  # => eax
17027         (string-equal? %eax "esi")  # => eax
17028         3d/compare-eax-and 0/imm32/false
17029         0f 85/jump-if-!= $parse-mu-var-def:error-byte-registers/disp32
17030         (lookup *(esi+0x18) *(esi+0x1c))  # => eax
17031         (string-equal? %eax "edi")  # => eax
17032         3d/compare-eax-and 0/imm32/false
17033         0f 85/jump-if-!= $parse-mu-var-def:error-byte-registers/disp32
17034       }
17035       # TODO: vars of type 'byte' should only be initialized by clearing to 0
17036       # ensure that the next word is '<-'
17037       (next-mu-token *(ebp+8) %ecx)
17038       (slice-equal? %ecx "<-")  # => eax
17039       3d/compare-eax-and 0/imm32/false
17040       0f 84/jump-if-= $parse-mu-var-def:error1/disp32
17041       #
17042       (new-reg-var-def Heap  *edx *(edx+4)  %edi)
17043       (lookup *edi *(edi+4))  # => eax
17044       (add-operation-and-inputs-to-stmt %eax *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
17045     }
17046 $parse-mu-var-def:update-vars:
17047     # push 'v' at end of function
17048     (push *(ebp+0xc) *edx)
17049     (push *(ebp+0xc) *(edx+4))
17050     (push *(ebp+0xc) 0)  # Live-var-register-spilled is unused during parsing
17051 $parse-mu-var-def:end:
17052     # . reclaim locals
17053     81 0/subop/add %esp 0x10/imm32
17054     # . restore registers
17055     5f/pop-to-edi
17056     5e/pop-to-esi
17057     5a/pop-to-edx
17058     59/pop-to-ecx
17059     58/pop-to-eax
17060     # . epilogue
17061     89/<- %esp 5/r32/ebp
17062     5d/pop-to-ebp
17063     c3/return
17064 
17065 $parse-mu-var-def:error1:
17066     (rewind-stream *(ebp+8))
17067     # error("register variable requires a valid instruction to initialize but got '" line "'\n")
17068     (write-buffered *(ebp+0x18) "register variable requires a valid instruction to initialize but got '")
17069     (flush *(ebp+0x18))
17070     (write-stream-data *(ebp+0x18) *(ebp+8))
17071     (write-buffered *(ebp+0x18) "'\n")
17072     (flush *(ebp+0x18))
17073     (stop *(ebp+0x1c) 1)
17074     # never gets here
17075 
17076 $parse-mu-var-def:error2:
17077     # error("fn " fn ": var " var ": variables on the stack can't take an initializer\n")
17078     (write-buffered *(ebp+0x18) "fn ")
17079     8b/-> *(ebp+0x14) 0/r32/eax
17080     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17081     (write-buffered *(ebp+0x18) %eax)
17082     (write-buffered *(ebp+0x18) ": var ")
17083     # var v-addr/eax: (addr var) = lookup(v)
17084     (lookup *edx *(edx+4))  # => eax
17085     (lookup *eax *(eax+4))  # Var-name Var-name => eax
17086     (write-buffered *(ebp+0x18) %eax)
17087     (write-buffered *(ebp+0x18) ": variables on the stack can't take an initializer\n")
17088     (flush *(ebp+0x18))
17089     (stop *(ebp+0x1c) 1)
17090     # never gets here
17091 
17092 $parse-mu-var-def:error-byte-on-stack:
17093     # error("fn " fn ": var '" var "' of type 'byte' cannot be on the stack\n")
17094     (write-buffered *(ebp+0x18) "fn ")
17095     8b/-> *(ebp+0x14) 0/r32/eax
17096     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17097     (write-buffered *(ebp+0x18) %eax)
17098     (write-buffered *(ebp+0x18) ": var '")
17099     # var v-addr/eax: (addr var) = lookup(v)
17100     (lookup *edx *(edx+4))  # => eax
17101     (lookup *eax *(eax+4))  # Var-name Var-name => eax
17102     (write-buffered *(ebp+0x18) %eax)
17103     (write-buffered *(ebp+0x18) "' of type 'byte' cannot be on the stack\n")
17104     (flush *(ebp+0x18))
17105     (stop *(ebp+0x1c) 1)
17106     # never gets here
17107 
17108 $parse-mu-var-def:error-byte-registers:
17109     # error("fn " fn ": var '" var "' of type 'byte' cannot be in esi or edi\n")
17110     (write-buffered *(ebp+0x18) "fn ")
17111     8b/-> *(ebp+0x14) 0/r32/eax
17112     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17113     (write-buffered *(ebp+0x18) %eax)
17114     (write-buffered *(ebp+0x18) ": var '")
17115     # var v-addr/eax: (addr var) = lookup(v)
17116     (lookup *edx *(edx+4))  # => eax
17117     (lookup *eax *(eax+4))  # Var-name Var-name => eax
17118     (write-buffered *(ebp+0x18) %eax)
17119     (write-buffered *(ebp+0x18) "' of type 'byte' cannot be in esi or edi\n")
17120     (flush *(ebp+0x18))
17121     (stop *(ebp+0x1c) 1)
17122     # never gets here
17123 
17124 test-parse-mu-var-def:
17125     # 'var n: int'
17126     # . prologue
17127     55/push-ebp
17128     89/<- %ebp 4/r32/esp
17129     # setup
17130     8b/-> *Primitive-type-ids 0/r32/eax
17131     89/<- *Type-id 0/r32/eax  # stream-write
17132     (clear-stream _test-input-stream)
17133     (write _test-input-stream "n: int\n")  # caller has consumed the 'var'
17134     c7 0/subop/copy *Curr-block-depth 1/imm32
17135     # var out/esi: (handle stmt)
17136     68/push 0/imm32
17137     68/push 0/imm32
17138     89/<- %esi 4/r32/esp
17139     # var vars/ecx: (stack (addr var) 16)
17140     81 5/subop/subtract %esp 0xc0/imm32
17141     68/push 0xc0/imm32/size
17142     68/push 0/imm32/top
17143     89/<- %ecx 4/r32/esp
17144     (clear-stack %ecx)
17145     # convert
17146     (parse-mu-var-def _test-input-stream %ecx %esi 0 Stderr 0)
17147     # var out-addr/esi: (addr stmt)
17148     (lookup *esi *(esi+4))  # => eax
17149     89/<- %esi 0/r32/eax
17150     #
17151     (check-ints-equal *esi 2 "F - test-parse-mu-var-def/tag")  # Stmt-tag is var-def
17152     # var v/ecx: (addr var) = lookup(out->var)
17153     (lookup *(esi+4) *(esi+8))  # Vardef-var Vardef-var => eax
17154     89/<- %ecx 0/r32/eax
17155     # v->name
17156     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
17157     (check-strings-equal %eax "n" "F - test-parse-mu-var-def/var-name")
17158     # v->register
17159     (check-ints-equal *(ecx+0x18) 0 "F - test-parse-mu-var-def/var-register")  # Var-register
17160     # v->block-depth
17161     (check-ints-equal *(ecx+0x10) 1 "F - test-parse-mu-var-def/output-block-depth")  # Var-block-depth
17162     # v->type == int
17163     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
17164     (check-ints-equal *eax 1 "F - test-parse-mu-var-def/var-type:0")  # Type-tree-is-atom
17165     (check-ints-equal *(eax+4) 1 "F - test-parse-mu-var-def/var-type:1")  # Type-tree-value
17166     (check-ints-equal *(eax+0xc) 0 "F - test-parse-mu-var-def/var-type:2")  # Type-tree-right
17167     # . epilogue
17168     89/<- %esp 5/r32/ebp
17169     5d/pop-to-ebp
17170     c3/return
17171 
17172 test-parse-mu-reg-var-def:
17173     # 'var n/eax: int <- copy 0'
17174     # . prologue
17175     55/push-ebp
17176     89/<- %ebp 4/r32/esp
17177     # setup
17178     8b/-> *Primitive-type-ids 0/r32/eax
17179     89/<- *Type-id 0/r32/eax  # stream-write
17180     (clear-stream _test-input-stream)
17181     (write _test-input-stream "n/eax: int <- copy 0\n")  # caller has consumed the 'var'
17182     c7 0/subop/copy *Curr-block-depth 1/imm32
17183     # var out/esi: (handle stmt)
17184     68/push 0/imm32
17185     68/push 0/imm32
17186     89/<- %esi 4/r32/esp
17187     # var vars/ecx: (stack (addr var) 16)
17188     81 5/subop/subtract %esp 0xc0/imm32
17189     68/push 0xc0/imm32/size
17190     68/push 0/imm32/top
17191     89/<- %ecx 4/r32/esp
17192     (clear-stack %ecx)
17193     # convert
17194     (parse-mu-var-def _test-input-stream %ecx %esi 0 Stderr 0)
17195     # var out-addr/esi: (addr stmt)
17196     (lookup *esi *(esi+4))  # => eax
17197     89/<- %esi 0/r32/eax
17198     #
17199     (check-ints-equal *esi 3 "F - test-parse-mu-reg-var-def/tag")  # Stmt-tag is reg-var-def
17200     # var v/ecx: (addr var) = lookup(out->outputs->value)
17201     # . eax: (addr stmt-var) = lookup(out->outputs)
17202     (lookup *(esi+0x14) *(esi+0x18))  # Regvardef-outputs Regvardef-outputs => eax
17203     # .
17204     (check-ints-equal *(eax+8) 0 "F - test-parse-mu-reg-var-def/single-output")  # Stmt-var-next
17205     # . eax: (addr var) = lookup(eax->value)
17206     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
17207     # . ecx = eax
17208     89/<- %ecx 0/r32/eax
17209     # v->name
17210     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
17211     (check-strings-equal %eax "n" "F - test-parse-mu-reg-var-def/output-name")  # Var-name
17212     # v->register
17213     (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
17214     (check-strings-equal %eax "eax" "F - test-parse-mu-reg-var-def/output-register")
17215     # v->block-depth
17216     (check-ints-equal *(ecx+0x10) 1 "F - test-parse-mu-reg-var-def/output-block-depth")  # Var-block-depth
17217     # v->type == int
17218     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
17219     (check-ints-equal *eax 1 "F - test-parse-mu-reg-var-def/output-type:0")  # Type-tree-is-atom
17220     (check-ints-equal *(eax+4) 1 "F - test-parse-mu-reg-var-def/output-type:1")  # Type-tree-value
17221     (check-ints-equal *(eax+0xc) 0 "F - test-parse-mu-reg-var-def/output-type:2")  # Type-tree-right
17222     # . epilogue
17223     89/<- %esp 5/r32/ebp
17224     5d/pop-to-ebp
17225     c3/return
17226 
17227 parse-mu-stmt:  # line: (addr stream byte), vars: (addr stack live-var), fn: (addr function), out: (addr handle stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
17228     # pseudocode:
17229     #   var name: slice
17230     #   allocate(Heap, Stmt-size, out)
17231     #   var out-addr: (addr stmt) = lookup(*out)
17232     #   out-addr->tag = stmt
17233     #   if stmt-has-outputs?(line)
17234     #     while true
17235     #       name = next-mu-token(line)
17236     #       if (name == '<-') break
17237     #       assert(is-identifier?(name))
17238     #       var v: (handle var) = lookup-var(name, vars)
17239     #       out-addr->outputs = append(v, out-addr->outputs)
17240     #   add-operation-and-inputs-to-stmt(out-addr, line, vars)
17241     #
17242     # . prologue
17243     55/push-ebp
17244     89/<- %ebp 4/r32/esp
17245     # . save registers
17246     50/push-eax
17247     51/push-ecx
17248     52/push-edx
17249     53/push-ebx
17250     57/push-edi
17251     # var name/ecx: slice
17252     68/push 0/imm32/end
17253     68/push 0/imm32/start
17254     89/<- %ecx 4/r32/esp
17255     # var is-deref?/edx: boolean = false
17256     ba/copy-to-edx 0/imm32/false
17257     # var v: (handle var)
17258     68/push 0/imm32
17259     68/push 0/imm32
17260     89/<- %ebx 4/r32/esp
17261     #
17262     (allocate Heap *Stmt-size *(ebp+0x14))
17263     # var out-addr/edi: (addr stmt) = lookup(*out)
17264     8b/-> *(ebp+0x14) 7/r32/edi
17265     (lookup *edi *(edi+4))  # => eax
17266     89/<- %edi 0/r32/eax
17267     # out-addr->tag = 1/stmt
17268     c7 0/subop/copy *edi 1/imm32/stmt1  # Stmt-tag
17269     {
17270       (stmt-has-outputs? *(ebp+8))
17271       3d/compare-eax-and 0/imm32/false
17272       0f 84/jump-if-= break/disp32
17273       {
17274 $parse-mu-stmt:read-outputs:
17275         # name = next-mu-token(line)
17276         (next-mu-token *(ebp+8) %ecx)
17277         # if slice-empty?(word-slice) break
17278         (slice-empty? %ecx)  # => eax
17279         3d/compare-eax-and 0/imm32/false
17280         0f 85/jump-if-!= break/disp32
17281         # if (name == "<-") break
17282         (slice-equal? %ecx "<-")  # => eax
17283         3d/compare-eax-and 0/imm32/false
17284         0f 85/jump-if-!= break/disp32
17285         # if slice-starts-with?(name, "*") abort
17286         8b/-> *ecx 0/r32/eax  # Slice-start
17287         8a/copy-byte *eax 0/r32/AL
17288         81 4/subop/and %eax 0xff/imm32
17289         3d/compare-eax-and 0x2a/imm32/asterisk
17290         0f 84/jump-if-= $parse-mu-stmt:error-output-dereferenced/disp32
17291         # assert(is-identifier?(name))
17292         (is-identifier? %ecx)  # => eax
17293         3d/compare-eax-and 0/imm32/false
17294         0f 84/jump-if-= $parse-mu-stmt:abort/disp32
17295         #
17296         (lookup-var %ecx *(ebp+0xc) %ebx *(ebp+0x10) *(ebp+0x18) *(ebp+0x1c))
17297         8d/copy-address *(edi+0x14) 0/r32/eax  # Stmt1-outputs
17298         (append-stmt-var Heap  *ebx *(ebx+4)  *(edi+0x14) *(edi+0x18)  0  %eax)  # Stmt1-outputs
17299         #
17300         e9/jump loop/disp32
17301       }
17302     }
17303     (add-operation-and-inputs-to-stmt %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x18) *(ebp+0x1c))
17304 $parse-mu-stmt:end:
17305     # . reclaim locals
17306     81 0/subop/add %esp 0x10/imm32
17307     # . restore registers
17308     5f/pop-to-edi
17309     5b/pop-to-ebx
17310     5a/pop-to-edx
17311     59/pop-to-ecx
17312     58/pop-to-eax
17313     # . epilogue
17314     89/<- %esp 5/r32/ebp
17315     5d/pop-to-ebp
17316     c3/return
17317 
17318 $parse-mu-stmt:abort:
17319     # error("invalid identifier '" name "'\n")
17320     (write-buffered *(ebp+0x18) "fn ")
17321     8b/-> *(ebp+0x10) 0/r32/eax
17322     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17323     (write-buffered *(ebp+0x18) %eax)
17324     (write-buffered *(ebp+0x18) ": invalid identifier '")
17325     (write-slice-buffered *(ebp+0x18) %ecx)
17326     (write-buffered *(ebp+0x18) "'\n")
17327     (flush *(ebp+0x18))
17328     (stop *(ebp+0x1c) 1)
17329     # never gets here
17330 
17331 $parse-mu-stmt:error-output-dereferenced:
17332     # error("invalid identifier '" name "'\n")
17333     (write-buffered *(ebp+0x18) "fn ")
17334     8b/-> *(ebp+0x10) 0/r32/eax
17335     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17336     (write-buffered *(ebp+0x18) %eax)
17337     (write-buffered *(ebp+0x18) ": output '")
17338     (write-slice-buffered *(ebp+0x18) %ecx)
17339     (write-buffered *(ebp+0x18) "' should write to a register, and therefore cannot be dereferenced\n")
17340     (flush *(ebp+0x18))
17341     (stop *(ebp+0x1c) 1)
17342     # never gets here
17343 
17344 add-operation-and-inputs-to-stmt:  # stmt: (addr stmt), line: (addr stream byte), vars: (addr stack live-var), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
17345     # pseudocode:
17346     #   stmt->name = slice-to-string(next-mu-token(line))
17347     #   while true
17348     #     name = next-mu-token(line)
17349     #     v = lookup-var-or-literal(name)
17350     #     stmt->inouts = append(v, stmt->inouts)
17351     #
17352     # . prologue
17353     55/push-ebp
17354     89/<- %ebp 4/r32/esp
17355     # . save registers
17356     50/push-eax
17357     51/push-ecx
17358     52/push-edx
17359     53/push-ebx
17360     56/push-esi
17361     57/push-edi
17362     # edi = stmt
17363     8b/-> *(ebp+8) 7/r32/edi
17364     # var name/ecx: slice
17365     68/push 0/imm32/end
17366     68/push 0/imm32/start
17367     89/<- %ecx 4/r32/esp
17368     # var is-deref?/edx: boolean = false
17369     ba/copy-to-edx 0/imm32/false
17370     # var v/esi: (handle var)
17371     68/push 0/imm32
17372     68/push 0/imm32
17373     89/<- %esi 4/r32/esp
17374 $add-operation-and-inputs-to-stmt:read-operation:
17375     (next-mu-token *(ebp+0xc) %ecx)
17376     8d/copy-address *(edi+4) 0/r32/eax  # Stmt1-operation or Regvardef-operationStmt1-operation or Regvardef-operation
17377     (slice-to-string Heap %ecx %eax)
17378     # var is-get?/ebx: boolean = (name == "get")
17379     (slice-equal? %ecx "get")  # => eax
17380     89/<- %ebx 0/r32/eax
17381     {
17382 $add-operation-and-inputs-to-stmt:read-inouts:
17383       # name = next-mu-token(line)
17384       (next-mu-token *(ebp+0xc) %ecx)
17385       # if slice-empty?(word-slice) break
17386       (slice-empty? %ecx)  # => eax
17387       3d/compare-eax-and 0/imm32/false
17388       0f 85/jump-if-!= break/disp32
17389       # if (name == "<-") abort
17390       (slice-equal? %ecx "<-")
17391       3d/compare-eax-and 0/imm32/false
17392       0f 85/jump-if-!= $add-operation-and-inputs-to-stmt:abort/disp32
17393       # if (is-get? && second operand) lookup or create offset
17394       {
17395         81 7/subop/compare %ebx 0/imm32/false
17396         74/jump-if-= break/disp8
17397         (lookup *(edi+0xc) *(edi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
17398         3d/compare-eax-and 0/imm32
17399         74/jump-if-= break/disp8
17400         (lookup-or-create-constant %eax %ecx %esi)
17401 #?         (lookup *esi *(esi+4))
17402 #?         (write-buffered Stderr "creating new output var ")
17403 #?         (write-int32-hex-buffered Stderr %eax)
17404 #?         (write-buffered Stderr " for field called ")
17405 #?         (write-slice-buffered Stderr %ecx)
17406 #?         (write-buffered Stderr "; var name ")
17407 #?         (lookup *eax *(eax+4))  # Var-name
17408 #?         (write-buffered Stderr %eax)
17409 #?         (write-buffered Stderr Newline)
17410 #?         (flush Stderr)
17411         e9/jump $add-operation-and-inputs-to-stmt:save-var/disp32
17412       }
17413       # is-deref? = false
17414       ba/copy-to-edx 0/imm32/false
17415       # if (slice-starts-with?(name, '*')) ++name->start and set is-deref?
17416       8b/-> *ecx 0/r32/eax  # Slice-start
17417       8a/copy-byte *eax 0/r32/AL
17418       81 4/subop/and %eax 0xff/imm32
17419       3d/compare-eax-and 0x2a/imm32/asterisk
17420       {
17421         75/jump-if-!= break/disp8
17422 $add-operation-and-inputs-to-stmt:inout-is-deref:
17423         ff 0/subop/increment *ecx
17424         ba/copy-to-edx 1/imm32/true
17425       }
17426       (lookup-var-or-literal %ecx *(ebp+0x10) %esi *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
17427       # if (is-deref?) some additional checks
17428       81 7/subop/compare %edx 0/imm32/false
17429       {
17430         74/jump-if-= break/disp8
17431         # if var is not in register, abort
17432         (lookup *esi *(esi+4))  # => eax
17433         81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
17434         0f 84/jump-if-= $add-operation-and-inputs-to-stmt:error-deref-on-stack/disp32
17435         # if var is not an address, abort
17436         (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
17437         (is-mu-addr-type? %eax)  # => eax
17438         3d/compare-eax-and 0/imm32/false
17439         0f 84/jump-if-= $add-operation-and-inputs-to-stmt:error-deref-non-addr/disp32
17440       }
17441 $add-operation-and-inputs-to-stmt:save-var:
17442       8d/copy-address *(edi+0xc) 0/r32/eax
17443       (append-stmt-var Heap  *esi *(esi+4)  *(edi+0xc) *(edi+0x10)  %edx  %eax)  # Stmt1-inouts or Regvardef-inouts
17444       #
17445       e9/jump loop/disp32
17446     }
17447 $add-operation-and-inputs-to-stmt:end:
17448     # . reclaim locals
17449     81 0/subop/add %esp 0x10/imm32
17450     # . restore registers
17451     5f/pop-to-edi
17452     5e/pop-to-esi
17453     5b/pop-to-ebx
17454     5a/pop-to-edx
17455     59/pop-to-ecx
17456     58/pop-to-eax
17457     # . epilogue
17458     89/<- %esp 5/r32/ebp
17459     5d/pop-to-ebp
17460     c3/return
17461 
17462 $add-operation-and-inputs-to-stmt:abort:
17463     # error("fn ___: invalid identifier in '" line "'\n")
17464     (write-buffered *(ebp+0x18) "fn ")
17465     8b/-> *(ebp+0x14) 0/r32/eax
17466     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17467     (write-buffered *(ebp+0x18) %eax)
17468     (rewind-stream *(ebp+0xc))
17469     (write-buffered *(ebp+0x18) ": invalid identifier in '")
17470     (write-stream-data *(ebp+0x18) *(ebp+0xc))
17471     (write-buffered *(ebp+0x18) "'\n")
17472     (flush *(ebp+0x18))
17473     (stop *(ebp+0x1c) 1)
17474     # never gets here
17475 
17476 $add-operation-and-inputs-to-stmt:error-deref-on-stack:
17477     # error("fn ___: cannot dereference var ___ on stack\n")
17478     (write-buffered *(ebp+0x18) "fn ")
17479     8b/-> *(ebp+0x14) 0/r32/eax
17480     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17481     (write-buffered *(ebp+0x18) %eax)
17482     (rewind-stream *(ebp+0xc))
17483     (write-buffered *(ebp+0x18) ": cannot dereference var '")
17484     (lookup *esi *(esi+4))  # => eax
17485     (lookup *eax *(eax+4))  # Var-name Var-name => eax
17486     (write-buffered *(ebp+0x18) %eax)
17487     (write-buffered *(ebp+0x18) "' on stack\n")
17488     (flush *(ebp+0x18))
17489     (stop *(ebp+0x1c) 1)
17490     # never gets here
17491 
17492 $add-operation-and-inputs-to-stmt:error-deref-non-addr:
17493     # error("fn ___: cannot dereference non-addr var ___\n")
17494     (write-buffered *(ebp+0x18) "fn ")
17495     8b/-> *(ebp+0x14) 0/r32/eax
17496     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17497     (write-buffered *(ebp+0x18) %eax)
17498     (rewind-stream *(ebp+0xc))
17499     (write-buffered *(ebp+0x18) ": cannot dereference non-addr var '")
17500     (lookup *esi *(esi+4))  # => eax
17501     (lookup *eax *(eax+4))  # Var-name Var-name => eax
17502     (write-buffered *(ebp+0x18) %eax)
17503     (write-buffered *(ebp+0x18) "'\n")
17504     (flush *(ebp+0x18))
17505     (stop *(ebp+0x1c) 1)
17506     # never gets here
17507 
17508 stmt-has-outputs?:  # line: (addr stream byte) -> result/eax: boolean
17509     # . prologue
17510     55/push-ebp
17511     89/<- %ebp 4/r32/esp
17512     # . save registers
17513     51/push-ecx
17514     # var word-slice/ecx: slice
17515     68/push 0/imm32/end
17516     68/push 0/imm32/start
17517     89/<- %ecx 4/r32/esp
17518     # result = false
17519     b8/copy-to-eax 0/imm32/false
17520     (rewind-stream *(ebp+8))
17521     {
17522       (next-mu-token *(ebp+8) %ecx)
17523       # if slice-empty?(word-slice) break
17524       (slice-empty? %ecx)
17525       3d/compare-eax-and 0/imm32/false
17526       b8/copy-to-eax 0/imm32/false/result  # restore result (if we're here it's still false)
17527       0f 85/jump-if-!= break/disp32
17528       # if slice-starts-with?(word-slice, '#') break
17529       # . eax = *word-slice->start
17530       8b/-> *ecx 0/r32/eax
17531       8a/copy-byte *eax 0/r32/AL
17532       81 4/subop/and %eax 0xff/imm32
17533       # . if (eax == '#') break
17534       3d/compare-eax-and 0x23/imm32/hash
17535       b8/copy-to-eax 0/imm32/false/result  # restore result (if we're here it's still false)
17536       0f 84/jump-if-= break/disp32
17537       # if slice-equal?(word-slice, '<-') return true
17538       (slice-equal? %ecx "<-")
17539       3d/compare-eax-and 0/imm32/false
17540       74/jump-if-= loop/disp8
17541       b8/copy-to-eax 1/imm32/true
17542     }
17543 $stmt-has-outputs:end:
17544     (rewind-stream *(ebp+8))
17545     # . reclaim locals
17546     81 0/subop/add %esp 8/imm32
17547     # . restore registers
17548     59/pop-to-ecx
17549     # . epilogue
17550     89/<- %esp 5/r32/ebp
17551     5d/pop-to-ebp
17552     c3/return
17553 
17554 # if 'name' starts with a digit, create a new literal var for it
17555 # otherwise return first 'name' from the top (back) of 'vars' and abort if not found
17556 lookup-var-or-literal:  # name: (addr slice), vars: (addr stack live-var), out: (addr handle var), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
17557     # . prologue
17558     55/push-ebp
17559     89/<- %ebp 4/r32/esp
17560     # . save registers
17561     50/push-eax
17562     51/push-ecx
17563     56/push-esi
17564     # esi = name
17565     8b/-> *(ebp+8) 6/r32/esi
17566     # if slice-empty?(name) abort
17567     (slice-empty? %esi)  # => eax
17568     3d/compare-eax-and 0/imm32/false
17569     0f 85/jump-if-!= $lookup-var-or-literal:abort/disp32
17570     # var c/ecx: byte = *name->start
17571     8b/-> *esi 1/r32/ecx
17572     8a/copy-byte *ecx 1/r32/CL
17573     81 4/subop/and %ecx 0xff/imm32
17574     # if (is-decimal-digit?(c) || c == '-') return new var(name)
17575     {
17576       81 7/subop/compare %ecx 0x2d/imm32/dash
17577       74/jump-if-= $lookup-var-or-literal:literal/disp8
17578       (is-decimal-digit? %ecx)  # => eax
17579       3d/compare-eax-and 0/imm32/false
17580       74/jump-if-= break/disp8
17581 $lookup-var-or-literal:literal:
17582       (new-literal-integer Heap %esi *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
17583       eb/jump $lookup-var-or-literal:end/disp8
17584     }
17585     # else if (c == '"') return new var(name)
17586     {
17587       81 7/subop/compare %ecx 0x22/imm32/dquote
17588       75/jump-if-!= break/disp8
17589 $lookup-var-or-literal:literal-string:
17590       (new-literal-string Heap %esi *(ebp+0x10))
17591       eb/jump $lookup-var-or-literal:end/disp8
17592     }
17593     # otherwise return lookup-var(name, vars)
17594     {
17595 $lookup-var-or-literal:var:
17596       (lookup-var %esi *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
17597     }
17598 $lookup-var-or-literal:end:
17599     # . restore registers
17600     5e/pop-to-esi
17601     59/pop-to-ecx
17602     58/pop-to-eax
17603     # . epilogue
17604     89/<- %esp 5/r32/ebp
17605     5d/pop-to-ebp
17606     c3/return
17607 
17608 $lookup-var-or-literal:abort:
17609     (write-buffered *(ebp+0x18) "fn ")
17610     8b/-> *(ebp+0x14) 0/r32/eax
17611     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17612     (write-buffered *(ebp+0x18) %eax)
17613     (write-buffered *(ebp+0x18) ": empty variable!")
17614     (flush *(ebp+0x18))
17615     (stop *(ebp+0x1c) 1)
17616     # never gets here
17617 
17618 # return first 'name' from the top (back) of 'vars' and abort if not found
17619 lookup-var:  # name: (addr slice), vars: (addr stack live-var), out: (addr handle var), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
17620     # . prologue
17621     55/push-ebp
17622     89/<- %ebp 4/r32/esp
17623     # . save registers
17624     50/push-eax
17625     #
17626     (lookup-var-helper *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
17627     # if (*out == 0) abort
17628     8b/-> *(ebp+0x10) 0/r32/eax
17629     81 7/subop/compare *eax 0/imm32
17630     74/jump-if-= $lookup-var:abort/disp8
17631 $lookup-var:end:
17632     # . restore registers
17633     58/pop-to-eax
17634     # . epilogue
17635     89/<- %esp 5/r32/ebp
17636     5d/pop-to-ebp
17637     c3/return
17638 
17639 $lookup-var:abort:
17640     (write-buffered *(ebp+0x18) "fn ")
17641     8b/-> *(ebp+0x14) 0/r32/eax
17642     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17643     (write-buffered *(ebp+0x18) %eax)
17644     (write-buffered *(ebp+0x18) ": unknown variable '")
17645     (write-slice-buffered *(ebp+0x18) *(ebp+8))
17646     (write-buffered *(ebp+0x18) "'\n")
17647     (flush *(ebp+0x18))
17648     (stop *(ebp+0x1c) 1)
17649     # never gets here
17650 
17651 # return first 'name' from the top (back) of 'vars', and 0/null if not found
17652 # ensure that 'name' if in a register is the topmost variable in that register
17653 lookup-var-helper:  # name: (addr slice), vars: (addr stack live-var), out: (addr handle var), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
17654     # pseudocode:
17655     #   var curr: (addr handle var) = &vars->data[vars->top - 12]
17656     #   var min = vars->data
17657     #   while curr >= min
17658     #     var v: (handle var) = *curr
17659     #     if v->name == name
17660     #       return
17661     #     curr -= 12
17662     #
17663     # . prologue
17664     55/push-ebp
17665     89/<- %ebp 4/r32/esp
17666     # . save registers
17667     50/push-eax
17668     51/push-ecx
17669     52/push-edx
17670     53/push-ebx
17671     56/push-esi
17672     57/push-edi
17673     # clear out
17674     (zero-out *(ebp+0x10) *Handle-size)
17675     # esi = vars
17676     8b/-> *(ebp+0xc) 6/r32/esi
17677     # ebx = vars->top
17678     8b/-> *esi 3/r32/ebx
17679     # if (vars->top > vars->size) abort
17680     3b/compare<- *(esi+4) 0/r32/eax
17681     0f 8f/jump-if-> $lookup-var-helper:error1/disp32
17682     # var min/edx: (addr handle var) = vars->data
17683     8d/copy-address *(esi+8) 2/r32/edx
17684     # var curr/ebx: (addr handle var) = &vars->data[vars->top - 12]
17685     8d/copy-address *(esi+ebx-4) 3/r32/ebx  # vars + 8 + vars->type - 12
17686     # var var-in-reg/edi: 16 addrs
17687     68/push 0/imm32
17688     68/push 0/imm32
17689     68/push 0/imm32
17690     68/push 0/imm32
17691     68/push 0/imm32
17692     68/push 0/imm32
17693     68/push 0/imm32
17694     68/push 0/imm32
17695     68/push 0/imm32
17696     68/push 0/imm32
17697     68/push 0/imm32
17698     68/push 0/imm32
17699     68/push 0/imm32
17700     68/push 0/imm32
17701     68/push 0/imm32
17702     68/push 0/imm32
17703     89/<- %edi 4/r32/esp
17704     {
17705 $lookup-var-helper:loop:
17706       # if (curr < min) return
17707       39/compare %ebx 2/r32/edx
17708       0f 82/jump-if-addr< break/disp32
17709       # var v/ecx: (addr var) = lookup(*curr)
17710       (lookup *ebx *(ebx+4))  # => eax
17711       89/<- %ecx 0/r32/eax
17712       # var vn/eax: (addr array byte) = lookup(v->name)
17713       (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
17714       # if (vn == name) return curr
17715       (slice-equal? *(ebp+8) %eax)  # => eax
17716       3d/compare-eax-and 0/imm32/false
17717       {
17718         74/jump-if-= break/disp8
17719 $lookup-var-helper:found:
17720         # var vr/eax: (addr array byte) = lookup(v->register)
17721         (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
17722         3d/compare-eax-and 0/imm32
17723         {
17724           74/jump-if-= break/disp8
17725 $lookup-var-helper:found-register:
17726           # var reg/eax: int = get(Registers, vr)
17727           (get Mu-registers-unique %eax 0xc "Mu-registers-unique")  # => eax
17728           8b/-> *eax 0/r32/eax
17729           # if (var-in-reg[reg]) error
17730           8b/-> *(edi+eax<<2) 0/r32/eax
17731           3d/compare-eax-and 0/imm32
17732           0f 85/jump-if-!= $lookup-var-helper:error2/disp32
17733         }
17734 $lookup-var-helper:return:
17735         # esi = out
17736         8b/-> *(ebp+0x10) 6/r32/esi
17737         # *out = *curr
17738         8b/-> *ebx 0/r32/eax
17739         89/<- *esi 0/r32/eax
17740         8b/-> *(ebx+4) 0/r32/eax
17741         89/<- *(esi+4) 0/r32/eax
17742         # return
17743         eb/jump $lookup-var-helper:end/disp8
17744       }
17745       # 'name' not yet found; update var-in-reg if v in register
17746       # . var vr/eax: (addr array byte) = lookup(v->register)
17747       (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
17748       # . if (vr == 0) continue
17749       3d/compare-eax-and 0/imm32
17750       74/jump-if-= $lookup-var-helper:continue/disp8
17751       # . var reg/eax: int = get(Registers, vr)
17752       (get Mu-registers-unique %eax 0xc "Mu-registers-unique")  # => eax
17753       8b/-> *eax 0/r32/eax
17754       # . var-in-reg[reg] = v
17755       89/<- *(edi+eax<<2) 1/r32/ecx
17756 $lookup-var-helper:continue:
17757       # curr -= 12
17758       81 5/subop/subtract %ebx 0xc/imm32
17759       e9/jump loop/disp32
17760     }
17761 $lookup-var-helper:end:
17762     # . reclaim locals
17763     81 0/subop/add %esp 0x40/imm32
17764     # . restore registers
17765     5f/pop-to-edi
17766     5e/pop-to-esi
17767     5b/pop-to-ebx
17768     5a/pop-to-edx
17769     59/pop-to-ecx
17770     58/pop-to-eax
17771     # . epilogue
17772     89/<- %esp 5/r32/ebp
17773     5d/pop-to-ebp
17774     c3/return
17775 
17776 $lookup-var-helper:error1:
17777     (write-buffered *(ebp+0x18) "fn ")
17778     8b/-> *(ebp+0x14) 0/r32/eax
17779     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17780     (write-buffered *(ebp+0x18) %eax)
17781     (write-buffered *(ebp+0x18) ": malformed stack when looking up '")
17782     (write-slice-buffered *(ebp+0x18) *(ebp+8))
17783     (write-buffered *(ebp+0x18) "'\n")
17784     (flush *(ebp+0x18))
17785     (stop *(ebp+0x1c) 1)
17786     # never gets here
17787 
17788 $lookup-var-helper:error2:
17789     # eax contains the conflicting var at this point
17790     (write-buffered *(ebp+0x18) "fn ")
17791     50/push-eax
17792     8b/-> *(ebp+0x14) 0/r32/eax
17793     (lookup *eax *(eax+4))  # Function-name Function-name => eax
17794     (write-buffered *(ebp+0x18) %eax)
17795     58/pop-eax
17796     (write-buffered *(ebp+0x18) ": register ")
17797     50/push-eax
17798     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
17799     (write-buffered *(ebp+0x18) %eax)
17800     58/pop-to-eax
17801     (write-buffered *(ebp+0x18) " reads var '")
17802     (write-slice-buffered *(ebp+0x18) *(ebp+8))
17803     (write-buffered *(ebp+0x18) "' after writing var '")
17804     (lookup *eax *(eax+4))  # Var-name Var-name => eax
17805     (write-buffered *(ebp+0x18) %eax)
17806     (write-buffered *(ebp+0x18) "'\n")
17807     (flush *(ebp+0x18))
17808     (stop *(ebp+0x1c) 1)
17809     # never gets here
17810 
17811 dump-vars:  # vars: (addr stack live-var)
17812     # pseudocode:
17813     #   var curr: (addr handle var) = &vars->data[vars->top - 12]
17814     #   var min = vars->data
17815     #   while curr >= min
17816     #     var v: (handle var) = *curr
17817     #     print v
17818     #     curr -= 12
17819     #
17820     # . prologue
17821     55/push-ebp
17822     89/<- %ebp 4/r32/esp
17823     # . save registers
17824     52/push-edx
17825     53/push-ebx
17826     56/push-esi
17827     # esi = vars
17828     8b/-> *(ebp+8) 6/r32/esi
17829     # ebx = vars->top
17830     8b/-> *esi 3/r32/ebx
17831     # var min/edx: (addr handle var) = vars->data
17832     8d/copy-address *(esi+8) 2/r32/edx
17833     # var curr/ebx: (addr handle var) = &vars->data[vars->top - 12]
17834     8d/copy-address *(esi+ebx-4) 3/r32/ebx  # vars + 8 + vars->type - 12
17835     {
17836 $dump-vars:loop:
17837       # if (curr < min) return
17838       39/compare %ebx 2/r32/edx
17839       0f 82/jump-if-addr< break/disp32
17840       #
17841       (write-buffered Stderr "  var@")
17842       (dump-var 2 %ebx)
17843       # curr -= 12
17844       81 5/subop/subtract %ebx 0xc/imm32
17845       e9/jump loop/disp32
17846     }
17847 $dump-vars:end:
17848     # . restore registers
17849     5e/pop-to-esi
17850     5b/pop-to-ebx
17851     5a/pop-to-edx
17852     # . epilogue
17853     89/<- %esp 5/r32/ebp
17854     5d/pop-to-ebp
17855     c3/return
17856 
17857 == data
17858 # Like Registers, but no esp or ebp
17859 Mu-registers:  # (addr stream {(handle array byte), int})
17860   # a table is a stream
17861   0xa8/imm32/write
17862   0/imm32/read
17863   0xa8/imm32/length
17864   # data
17865   # general-purpose registers
17866   # it is perfectly ok to use fake alloc-ids -- as long as you never try to reclaim them
17867   0x11/imm32/alloc-id $Mu-register-eax/imm32 0/imm32
17868   0x11/imm32/alloc-id $Mu-register-ecx/imm32 1/imm32
17869   0x11/imm32/alloc-id $Mu-register-edx/imm32 2/imm32
17870   0x11/imm32/alloc-id $Mu-register-ebx/imm32 3/imm32
17871   0x11/imm32/alloc-id $Mu-register-esi/imm32 6/imm32
17872   0x11/imm32/alloc-id $Mu-register-edi/imm32 7/imm32
17873   # floating-point registers
17874   0x11/imm32/alloc-id $Mu-register-xmm0/imm32 0/imm32
17875   0x11/imm32/alloc-id $Mu-register-xmm1/imm32 1/imm32
17876   0x11/imm32/alloc-id $Mu-register-xmm2/imm32 2/imm32
17877   0x11/imm32/alloc-id $Mu-register-xmm3/imm32 3/imm32
17878   0x11/imm32/alloc-id $Mu-register-xmm4/imm32 4/imm32
17879   0x11/imm32/alloc-id $Mu-register-xmm5/imm32 5/imm32
17880   0x11/imm32/alloc-id $Mu-register-xmm6/imm32 6/imm32
17881   0x11/imm32/alloc-id $Mu-register-xmm7/imm32 7/imm32
17882 
17883 # Like Mu-registers, but with unique codes for integer and floating-point
17884 # registers.
17885 # Don't use this for code-generation, only for checking.
17886 Mu-registers-unique:  # (addr stream {(handle array byte), int})
17887   # a table is a stream
17888   0xa8/imm32/write
17889   0/imm32/read
17890   0xa8/imm32/length
17891   # data
17892   # general-purpose registers
17893   0x11/imm32/alloc-id $Mu-register-eax/imm32 0/imm32
17894   0x11/imm32/alloc-id $Mu-register-ecx/imm32 1/imm32
17895   0x11/imm32/alloc-id $Mu-register-edx/imm32 2/imm32
17896   0x11/imm32/alloc-id $Mu-register-ebx/imm32 3/imm32
17897   0x11/imm32/alloc-id $Mu-register-esi/imm32 6/imm32
17898   0x11/imm32/alloc-id $Mu-register-edi/imm32 7/imm32
17899   # floating-point registers
17900   0x11/imm32/alloc-id $Mu-register-xmm0/imm32 8/imm32
17901   0x11/imm32/alloc-id $Mu-register-xmm1/imm32 9/imm32
17902   0x11/imm32/alloc-id $Mu-register-xmm2/imm32 0xa/imm32
17903   0x11/imm32/alloc-id $Mu-register-xmm3/imm32 0xb/imm32
17904   0x11/imm32/alloc-id $Mu-register-xmm4/imm32 0xc/imm32
17905   0x11/imm32/alloc-id $Mu-register-xmm5/imm32 0xd/imm32
17906   0x11/imm32/alloc-id $Mu-register-xmm6/imm32 0xe/imm32
17907   0x11/imm32/alloc-id $Mu-register-xmm7/imm32 0xf/imm32
17908 
17909 $Mu-register-eax:
17910   0x11/imm32/alloc-id
17911   3/imm32/size
17912   0x65/e 0x61/a 0x78/x
17913 
17914 $Mu-register-ecx:
17915   0x11/imm32/alloc-id
17916   3/imm32/size
17917   0x65/e 0x63/c 0x78/x
17918 
17919 $Mu-register-edx:
17920   0x11/imm32/alloc-id
17921   3/imm32/size
17922   0x65/e 0x64/d 0x78/x
17923 
17924 $Mu-register-ebx:
17925   0x11/imm32/alloc-id
17926   3/imm32/size
17927   0x65/e 0x62/b 0x78/x
17928 
17929 $Mu-register-esi:
17930   0x11/imm32/alloc-id
17931   3/imm32/size
17932   0x65/e 0x73/s 0x69/i
17933 
17934 $Mu-register-edi:
17935   0x11/imm32/alloc-id
17936   3/imm32/size
17937   0x65/e 0x64/d 0x69/i
17938 
17939 $Mu-register-xmm0:
17940   0x11/imm32/alloc-id:fake:payload
17941   # "xmm0"
17942   0x4/imm32/size
17943   0x78/x 0x6d/m 0x6d/m 0x30/0
17944 
17945 $Mu-register-xmm1:
17946   0x11/imm32/alloc-id:fake:payload
17947   # "xmm1"
17948   0x4/imm32/size
17949   0x78/x 0x6d/m 0x6d/m 0x31/1
17950 
17951 $Mu-register-xmm2:
17952   0x11/imm32/alloc-id:fake:payload
17953   # "xmm2"
17954   0x4/imm32/size
17955   0x78/x 0x6d/m 0x6d/m 0x32/2
17956 
17957 $Mu-register-xmm3:
17958   0x11/imm32/alloc-id:fake:payload
17959   # "xmm3"
17960   0x4/imm32/size
17961   0x78/x 0x6d/m 0x6d/m 0x33/3
17962 
17963 $Mu-register-xmm4:
17964   0x11/imm32/alloc-id:fake:payload
17965   # "xmm4"
17966   0x4/imm32/size
17967   0x78/x 0x6d/m 0x6d/m 0x34/4
17968 
17969 $Mu-register-xmm5:
17970   0x11/imm32/alloc-id:fake:payload
17971   # "xmm5"
17972   0x4/imm32/size
17973   0x78/x 0x6d/m 0x6d/m 0x35/5
17974 
17975 $Mu-register-xmm6:
17976   0x11/imm32/alloc-id:fake:payload
17977   # "xmm6"
17978   0x4/imm32/size
17979   0x78/x 0x6d/m 0x6d/m 0x36/6
17980 
17981 $Mu-register-xmm7:
17982   0x11/imm32/alloc-id:fake:payload
17983   # "xmm7"
17984   0x4/imm32/size
17985   0x78/x 0x6d/m 0x6d/m 0x37/7
17986 
17987 == code
17988 
17989 # push 'out' to 'vars' if not already there; it's assumed to be a fn output
17990 maybe-define-var:  # out: (handle var), vars: (addr stack live-var)
17991     # . prologue
17992     55/push-ebp
17993     89/<- %ebp 4/r32/esp
17994     # . save registers
17995     50/push-eax
17996     # var out-addr/eax: (addr var)
17997     (lookup *(ebp+8) *(ebp+0xc))  # => eax
17998     #
17999     (binding-exists? %eax *(ebp+0x10))  # => eax
18000     3d/compare-eax-and 0/imm32/false
18001     75/jump-if-!= $maybe-define-var:end/disp8
18002     # otherwise update vars
18003     (push *(ebp+0x10) *(ebp+8))
18004     (push *(ebp+0x10) *(ebp+0xc))
18005     (push *(ebp+0x10) 0)  # 'out' is always a fn output; never spill it
18006 $maybe-define-var:end:
18007     # . restore registers
18008     58/pop-to-eax
18009     # . epilogue
18010     89/<- %esp 5/r32/ebp
18011     5d/pop-to-ebp
18012     c3/return
18013 
18014 # simpler version of lookup-var-helper
18015 binding-exists?:  # target: (addr var), vars: (addr stack live-var) -> result/eax: boolean
18016     # pseudocode:
18017     #   var curr: (addr handle var) = &vars->data[vars->top - 12]
18018     #   var min = vars->data
18019     #   while curr >= min
18020     #     var v: (handle var) = *curr
18021     #     if v->name == target->name
18022     #       return true
18023     #     curr -= 12
18024     #   return false
18025     #
18026     # . prologue
18027     55/push-ebp
18028     89/<- %ebp 4/r32/esp
18029     # . save registers
18030     51/push-ecx
18031     52/push-edx
18032     56/push-esi
18033     # var target-name/ecx: (addr array byte) = lookup(target->name)
18034     8b/-> *(ebp+8) 0/r32/eax
18035     (lookup *eax *(eax+4))  # Var-name Var-name => eax
18036     89/<- %ecx 0/r32/eax
18037     # esi = vars
18038     8b/-> *(ebp+0xc) 6/r32/esi
18039     # eax = vars->top
18040     8b/-> *esi 0/r32/eax
18041     # var min/edx: (addr handle var) = vars->data
18042     8d/copy-address *(esi+8) 2/r32/edx
18043     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
18044     8d/copy-address *(esi+eax-4) 6/r32/esi  # vars + 8 + vars->type - 12
18045     {
18046 $binding-exists?:loop:
18047       # if (curr < min) return
18048       39/compare %esi 2/r32/edx
18049       0f 82/jump-if-addr< break/disp32
18050       # var v/eax: (addr var) = lookup(*curr)
18051       (lookup *esi *(esi+4))  # => eax
18052       # var vn/eax: (addr array byte) = lookup(v->name)
18053       (lookup *eax *(eax+4))  # Var-name Var-name => eax
18054       # if (vn == target-name) return true
18055       (string-equal? %ecx %eax)  # => eax
18056       3d/compare-eax-and 0/imm32/false
18057       75/jump-if-!= $binding-exists?:end/disp8  # eax already contains true
18058       # curr -= 12
18059       81 5/subop/subtract %esi 0xc/imm32
18060       e9/jump loop/disp32
18061     }
18062     b8/copy-to-eax 0/imm32/false
18063 $binding-exists?:end:
18064     # . restore registers
18065     5e/pop-to-esi
18066     5a/pop-to-edx
18067     59/pop-to-ecx
18068     # . epilogue
18069     89/<- %esp 5/r32/ebp
18070     5d/pop-to-ebp
18071     c3/return
18072 
18073 test-parse-mu-stmt:
18074     # . prologue
18075     55/push-ebp
18076     89/<- %ebp 4/r32/esp
18077     # setup
18078     8b/-> *Primitive-type-ids 0/r32/eax
18079     89/<- *Type-id 0/r32/eax  # stream-write
18080     (clear-stream _test-input-stream)
18081     (write _test-input-stream "increment n\n")
18082     # var vars/ecx: (stack (addr var) 16)
18083     81 5/subop/subtract %esp 0xc0/imm32
18084     68/push 0xc0/imm32/size
18085     68/push 0/imm32/top
18086     89/<- %ecx 4/r32/esp
18087     (clear-stack %ecx)
18088     # var v/edx: (handle var)
18089     68/push 0/imm32
18090     68/push 0/imm32
18091     89/<- %edx 4/r32/esp
18092     # var s/eax: (handle array byte)
18093     68/push 0/imm32
18094     68/push 0/imm32
18095     89/<- %eax 4/r32/esp
18096     # v = new var("n")
18097     (copy-array Heap "n" %eax)
18098     (new-var Heap *eax *(eax+4) %edx)
18099     #
18100     (push %ecx *edx)
18101     (push %ecx *(edx+4))
18102     (push %ecx 0)
18103     # var out/eax: (handle stmt)
18104     68/push 0/imm32
18105     68/push 0/imm32
18106     89/<- %eax 4/r32/esp
18107     # convert
18108     (parse-mu-stmt _test-input-stream %ecx 0 %eax Stderr 0)
18109     # var out-addr/edx: (addr stmt) = lookup(*out)
18110     (lookup *eax *(eax+4))  # => eax
18111     89/<- %edx 0/r32/eax
18112     # out->tag
18113     (check-ints-equal *edx 1 "F - test-parse-mu-stmt/tag")  # Stmt-tag is Stmt1
18114     # out->operation
18115     (lookup *(edx+4) *(edx+8))  # Stmt1-operation Stmt1-operation => eax
18116     (check-strings-equal %eax "increment" "F - test-parse-mu-stmt/name")  # Stmt1-operation
18117     # out->inouts->value->name
18118     # . eax = out->inouts
18119     (lookup *(edx+0xc) *(edx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
18120     # . eax = out->inouts->value
18121     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
18122     # . eax = out->inouts->value->name
18123     (lookup *eax *(eax+4))  # Var-name Var-name => eax
18124     # .
18125     (check-strings-equal %eax "n" "F - test-parse-mu-stmt/inout:0")
18126     # . epilogue
18127     89/<- %esp 5/r32/ebp
18128     5d/pop-to-ebp
18129     c3/return
18130 
18131 test-parse-mu-stmt-with-comma:
18132     # . prologue
18133     55/push-ebp
18134     89/<- %ebp 4/r32/esp
18135     # setup
18136     8b/-> *Primitive-type-ids 0/r32/eax
18137     89/<- *Type-id 0/r32/eax  # stream-write
18138     (clear-stream _test-input-stream)
18139     (write _test-input-stream "copy-to n, 3\n")
18140     # var vars/ecx: (stack (addr var) 16)
18141     81 5/subop/subtract %esp 0xc0/imm32
18142     68/push 0xc0/imm32/size
18143     68/push 0/imm32/top
18144     89/<- %ecx 4/r32/esp
18145     (clear-stack %ecx)
18146     # var v/edx: (handle var)
18147     68/push 0/imm32
18148     68/push 0/imm32
18149     89/<- %edx 4/r32/esp
18150     # var s/eax: (handle array byte)
18151     68/push 0/imm32
18152     68/push 0/imm32
18153     89/<- %eax 4/r32/esp
18154     # v = new var("n")
18155     (copy-array Heap "n" %eax)
18156     (new-var Heap *eax *(eax+4) %edx)
18157     #
18158     (push %ecx *edx)
18159     (push %ecx *(edx+4))
18160     (push %ecx 0)
18161     # var out/eax: (handle stmt)
18162     68/push 0/imm32
18163     68/push 0/imm32
18164     89/<- %eax 4/r32/esp
18165     # convert
18166     (parse-mu-stmt _test-input-stream %ecx 0 %eax Stderr 0)
18167     # var out-addr/edx: (addr stmt) = lookup(*out)
18168     (lookup *eax *(eax+4))  # => eax
18169     89/<- %edx 0/r32/eax
18170     # out->tag
18171     (check-ints-equal *edx 1 "F - test-parse-mu-stmt-with-comma/tag")  # Stmt-tag is Stmt1
18172     # out->operation
18173     (lookup *(edx+4) *(edx+8))  # Stmt1-operation Stmt1-operation => eax
18174     (check-strings-equal %eax "copy-to" "F - test-parse-mu-stmt-with-comma/name")  # Stmt1-operation
18175     # out->inouts->value->name
18176     # . eax = out->inouts
18177     (lookup *(edx+0xc) *(edx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
18178     # . eax = out->inouts->value
18179     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
18180     # . eax = out->inouts->value->name
18181     (lookup *eax *(eax+4))  # Var-name Var-name => eax
18182     # .
18183     (check-strings-equal %eax "n" "F - test-parse-mu-stmt-with-comma/inout:0")
18184     # . epilogue
18185     89/<- %esp 5/r32/ebp
18186     5d/pop-to-ebp
18187     c3/return
18188 
18189 new-var:  # ad: (addr allocation-descriptor), name: (handle array byte), out: (addr handle var)
18190     # . prologue
18191     55/push-ebp
18192     89/<- %ebp 4/r32/esp
18193     # . save registers
18194     50/push-eax
18195     51/push-ecx
18196     # ecx = out
18197     8b/-> *(ebp+0x14) 1/r32/ecx
18198     #
18199     (allocate *(ebp+8) *Var-size %ecx)
18200     # var out-addr/eax: (addr var)
18201     (lookup *ecx *(ecx+4))  # => eax
18202     # out-addr->name = name
18203     8b/-> *(ebp+0xc) 1/r32/ecx
18204     89/<- *eax 1/r32/ecx  # Var-name
18205     8b/-> *(ebp+0x10) 1/r32/ecx
18206     89/<- *(eax+4) 1/r32/ecx  # Var-name
18207 #?     (write-buffered Stderr "var ")
18208 #?     (lookup *(ebp+0xc) *(ebp+0x10))
18209 #?     (write-buffered Stderr %eax)
18210 #?     (write-buffered Stderr " at ")
18211 #?     8b/-> *(ebp+0x14) 1/r32/ecx
18212 #?     (lookup *ecx *(ecx+4))  # => eax
18213 #?     (write-int32-hex-buffered Stderr %eax)
18214 #?     (write-buffered Stderr Newline)
18215 #?     (flush Stderr)
18216 $new-var:end:
18217     # . restore registers
18218     59/pop-to-ecx
18219     58/pop-to-eax
18220     # . epilogue
18221     89/<- %esp 5/r32/ebp
18222     5d/pop-to-ebp
18223     c3/return
18224 
18225 new-literal-integer:  # ad: (addr allocation-descriptor), name: (addr slice), out: (addr handle var), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
18226     # . prologue
18227     55/push-ebp
18228     89/<- %ebp 4/r32/esp
18229     # . save registers
18230     50/push-eax
18231     51/push-ecx
18232     # if (!is-hex-int?(name)) abort
18233     (is-hex-int? *(ebp+0xc))  # => eax
18234     3d/compare-eax-and 0/imm32/false
18235     0f 84/jump-if-= $new-literal-integer:abort/disp32
18236     # a little more error-checking
18237     (check-mu-hex-int *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
18238     # out = new var(s)
18239     (new-var-from-slice *(ebp+8) *(ebp+0xc) *(ebp+0x10))
18240     # var out-addr/ecx: (addr var) = lookup(*out)
18241     8b/-> *(ebp+0x10) 0/r32/eax
18242     (lookup *eax *(eax+4))  # => eax
18243     89/<- %ecx 0/r32/eax
18244     # out-addr->block-depth = *Curr-block-depth
18245     8b/-> *Curr-block-depth 0/r32/eax
18246     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
18247     # out-addr->type = new tree()
18248     8d/copy-address *(ecx+8) 0/r32/eax  # Var-type
18249     (allocate *(ebp+8) *Type-tree-size %eax)
18250     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
18251     c7 0/subop/copy *eax 1/imm32/true  # Type-tree-is-atom
18252     # nothing else to do; default type is 'literal'
18253 $new-literal-integer:end:
18254     # . reclaim locals
18255     81 0/subop/add %esp 8/imm32
18256     # . restore registers
18257     59/pop-to-ecx
18258     58/pop-to-eax
18259     # . epilogue
18260     89/<- %esp 5/r32/ebp
18261     5d/pop-to-ebp
18262     c3/return
18263 
18264 $new-literal-integer:abort:
18265     (write-buffered *(ebp+0x18) "fn ")
18266     8b/-> *(ebp+0x14) 0/r32/eax
18267     (lookup *eax *(eax+4))  # Function-name Function-name => eax
18268     (write-buffered *(ebp+0x18) %eax)
18269     (write-buffered *(ebp+0x18) ": variable '")
18270     (write-slice-buffered *(ebp+0x18) *(ebp+0xc))
18271     (write-buffered *(ebp+0x18) "' cannot begin with a digit (or do you have a typo in a number?)\n")
18272     (flush *(ebp+0x18))
18273     (stop *(ebp+0x1c) 1)
18274     # never gets here
18275 
18276 # precondition: name is a valid hex integer; require a '0x' prefix
18277 check-mu-hex-int:  # name: (addr slice), err: (addr buffered-file), ed: (addr exit-descriptor)
18278     # . prologue
18279     55/push-ebp
18280     89/<- %ebp 4/r32/esp
18281     # . save registers
18282     50/push-eax
18283     51/push-ecx
18284     52/push-edx
18285     # ecx = name
18286     8b/-> *(ebp+8) 1/r32/ecx
18287     # var start/edx: (addr byte) = name->start
18288     8b/-> *ecx 2/r32/edx
18289     # if (*start == '-') ++start
18290     b8/copy-to-eax 0/imm32
18291     8a/copy-byte *edx 0/r32/AL
18292     3d/compare-eax-and 0x2d/imm32/dash
18293     {
18294       75/jump-if-!= break/disp8
18295       42/increment-edx
18296     }
18297     # var end/ecx: (addr byte) = name->end
18298     8b/-> *(ecx+4) 1/r32/ecx
18299     # var len/eax: int = name->end - name->start
18300     89/<- %eax 1/r32/ecx
18301     29/subtract-from %eax 2/r32/edx
18302     # if (len <= 1) return
18303     3d/compare-eax-with 1/imm32
18304     0f 8e/jump-if-<= $check-mu-hex-int:end/disp32
18305 $check-mu-hex-int:length->-1:
18306     # if slice-starts-with?({start, end}, "0x") return
18307     # . var tmp = {start, end}
18308     51/push-ecx
18309     52/push-edx
18310     89/<- %eax 4/r32/esp
18311     # .
18312     (slice-starts-with? %eax "0x")  # => eax
18313     # . reclaim tmp
18314     81 0/subop/add %esp 8/imm32
18315     # .
18316     3d/compare-eax-with 0/imm32/false
18317     75/jump-if-!= $check-mu-hex-int:end/disp8
18318 $check-mu-hex-int:abort:
18319     # otherwise abort
18320     (write-buffered *(ebp+0xc) "literal integers are always hex in Mu; start '")
18321     (write-slice-buffered *(ebp+0xc) *(ebp+8))
18322     (write-buffered *(ebp+0xc) "' with a '0x' to be unambiguous, converting it to hexadecimal as necessary.\n")
18323     (flush *(ebp+0xc))
18324     (stop *(ebp+0x10) 1)
18325 $check-mu-hex-int:end:
18326     # . restore registers
18327     5a/pop-to-edx
18328     59/pop-to-ecx
18329     58/pop-to-eax
18330     # . epilogue
18331     89/<- %esp 5/r32/ebp
18332     5d/pop-to-ebp
18333     c3/return
18334 
18335 new-literal:  # ad: (addr allocation-descriptor), name: (addr slice), out: (addr handle var)
18336     # . prologue
18337     55/push-ebp
18338     89/<- %ebp 4/r32/esp
18339     # . save registers
18340     50/push-eax
18341     51/push-ecx
18342     # var s/ecx: (handle array byte)
18343     68/push 0/imm32
18344     68/push 0/imm32
18345     89/<- %ecx 4/r32/esp
18346     # s = slice-to-string(name)
18347     (slice-to-string Heap *(ebp+0xc) %ecx)
18348     # allocate to out
18349     (new-var *(ebp+8) *ecx *(ecx+4) *(ebp+0x10))
18350     # var out-addr/ecx: (addr var) = lookup(*out)
18351     8b/-> *(ebp+0x10) 1/r32/ecx
18352     (lookup *ecx *(ecx+4))  # => eax
18353     89/<- %ecx 0/r32/eax
18354     # out-addr->block-depth = *Curr-block-depth
18355     8b/-> *Curr-block-depth 0/r32/eax
18356     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
18357     # out-addr->type/eax = new type
18358     8d/copy-address *(ecx+8) 0/r32/eax  # Var-type
18359     (allocate *(ebp+8) *Type-tree-size %eax)
18360     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
18361     # nothing else to do; default type is 'literal'
18362     c7 0/subop/copy *eax 1/imm32/true  # Type-tree-is-atom
18363 $new-literal:end:
18364     # . reclaim locals
18365     81 0/subop/add %esp 8/imm32
18366     # . restore registers
18367     59/pop-to-ecx
18368     58/pop-to-eax
18369     # . epilogue
18370     89/<- %esp 5/r32/ebp
18371     5d/pop-to-ebp
18372     c3/return
18373 
18374 new-literal-string:  # ad: (addr allocation-descriptor), name: (addr slice), out: (addr handle var)
18375     # . prologue
18376     55/push-ebp
18377     89/<- %ebp 4/r32/esp
18378     # . save registers
18379     50/push-eax
18380     51/push-ecx
18381     # var s/ecx: (handle array byte)
18382     68/push 0/imm32
18383     68/push 0/imm32
18384     89/<- %ecx 4/r32/esp
18385     # s = slice-to-string(name)
18386     (slice-to-string Heap *(ebp+0xc) %ecx)
18387     # allocate to out
18388     (new-var *(ebp+8) *ecx *(ecx+4) *(ebp+0x10))
18389     # var out-addr/ecx: (addr var) = lookup(*out)
18390     8b/-> *(ebp+0x10) 1/r32/ecx
18391     (lookup *ecx *(ecx+4))  # => eax
18392     89/<- %ecx 0/r32/eax
18393     # out-addr->block-depth = *Curr-block-depth
18394     8b/-> *Curr-block-depth 0/r32/eax
18395     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
18396     # out-addr->type/eax = new type
18397     8d/copy-address *(ecx+8) 0/r32/eax  # Var-type
18398     (allocate *(ebp+8) *Type-tree-size %eax)
18399     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
18400     # out-addr->type->value = literal-string
18401     c7 0/subop/copy *(eax+4) 0x10/imm32/type-id-string-literal  # Type-tree-value
18402     # out-addr->type->is-atom? = true
18403     c7 0/subop/copy *eax 1/imm32/true  # Type-tree-is-atom
18404 $new-literal-string:end:
18405     # . reclaim locals
18406     81 0/subop/add %esp 8/imm32
18407     # . restore registers
18408     59/pop-to-ecx
18409     58/pop-to-eax
18410     # . epilogue
18411     89/<- %esp 5/r32/ebp
18412     5d/pop-to-ebp
18413     c3/return
18414 
18415 new-var-from-slice:  # ad: (addr allocation-descriptor), name: (addr slice), out: (addr handle var)
18416     # . prologue
18417     55/push-ebp
18418     89/<- %ebp 4/r32/esp
18419     # . save registers
18420     51/push-ecx
18421     # var tmp/ecx: (handle array byte)
18422     68/push 0/imm32
18423     68/push 0/imm32
18424     89/<- %ecx 4/r32/esp
18425     # tmp = slice-to-string(name)
18426     (slice-to-string Heap *(ebp+0xc) %ecx)
18427     # out = new-var(tmp)
18428     (new-var *(ebp+8) *ecx *(ecx+4) *(ebp+0x10))
18429 $new-var-from-slice:end:
18430     # . reclaim locals
18431     81 0/subop/add %esp 8/imm32
18432     # . restore registers
18433     59/pop-to-ecx
18434     # . epilogue
18435     89/<- %esp 5/r32/ebp
18436     5d/pop-to-ebp
18437     c3/return
18438 
18439 new-var-def:  # ad: (addr allocation-descriptor), var: (handle var), out: (addr handle stmt)
18440     # . prologue
18441     55/push-ebp
18442     89/<- %ebp 4/r32/esp
18443     # . save registers
18444     50/push-eax
18445     51/push-ecx
18446     #
18447     (allocate *(ebp+8) *Stmt-size *(ebp+0x14))
18448     # var out-addr/eax: (addr stmt) = lookup(*out)
18449     8b/-> *(ebp+0x14) 0/r32/eax
18450     (lookup *eax *(eax+4))  # => eax
18451     # out-addr->tag = stmt
18452     c7 0/subop/copy *eax 2/imm32/tag/var-on-stack  # Stmt-tag
18453     # result->var = var
18454     8b/-> *(ebp+0xc) 1/r32/ecx
18455     89/<- *(eax+4) 1/r32/ecx  # Vardef-var
18456     8b/-> *(ebp+0x10) 1/r32/ecx
18457     89/<- *(eax+8) 1/r32/ecx  # Vardef-var
18458 $new-var-def:end:
18459     # . restore registers
18460     59/pop-to-ecx
18461     58/pop-to-eax
18462     # . epilogue
18463     89/<- %esp 5/r32/ebp
18464     5d/pop-to-ebp
18465     c3/return
18466 
18467 new-reg-var-def:  # ad: (addr allocation-descriptor), var: (handle var), out: (addr handle stmt)
18468     # . prologue
18469     55/push-ebp
18470     89/<- %ebp 4/r32/esp
18471     # . save registers
18472     50/push-eax
18473     # eax = out
18474     8b/-> *(ebp+0x14) 0/r32/eax
18475     #
18476     (allocate *(ebp+8) *Stmt-size %eax)
18477     # var out-addr/eax: (addr stmt) = lookup(*out)
18478     (lookup *eax *(eax+4))  # => eax
18479     # set tag
18480     c7 0/subop/copy *eax 3/imm32/tag/var-in-register  # Stmt-tag
18481     # set output
18482     8d/copy-address *(eax+0x14) 0/r32/eax  # Regvardef-outputs
18483     (append-stmt-var Heap  *(ebp+0xc) *(ebp+0x10)  0 0  0  %eax)
18484 $new-reg-var-def:end:
18485     # . restore registers
18486     58/pop-to-eax
18487     # . epilogue
18488     89/<- %esp 5/r32/ebp
18489     5d/pop-to-ebp
18490     c3/return
18491 
18492 append-list:  # ad: (addr allocation-descriptor), value: (handle _type), list: (handle list _type), out: (addr handle list _type)
18493     # . prologue
18494     55/push-ebp
18495     89/<- %ebp 4/r32/esp
18496     # . save registers
18497     50/push-eax
18498     51/push-ecx
18499     57/push-edi
18500     # edi = out
18501     8b/-> *(ebp+0x1c) 7/r32/edi
18502     # *out = new list
18503     (allocate *(ebp+8) *List-size %edi)
18504     # var out-addr/edi: (addr list _type) = lookup(*out)
18505     (lookup *edi *(edi+4))  # => eax
18506     89/<- %edi 0/r32/eax
18507     # out-addr->value = value
18508     8b/-> *(ebp+0xc) 0/r32/eax
18509     89/<- *edi 0/r32/eax  # List-value
18510     8b/-> *(ebp+0x10) 0/r32/eax
18511     89/<- *(edi+4) 0/r32/eax  # List-value
18512     # if (list == null) return
18513     81 7/subop/compare *(ebp+0x14) 0/imm32
18514     74/jump-if-= $append-list:end/disp8
18515     # otherwise append
18516 $append-list:non-empty-list:
18517     # var curr/eax: (addr list _type) = lookup(list)
18518     (lookup *(ebp+0x14) *(ebp+0x18))  # => eax
18519     # while (curr->next != null) curr = curr->next
18520     {
18521       81 7/subop/compare *(eax+8) 0/imm32  # List-next
18522       74/jump-if-= break/disp8
18523       # curr = lookup(curr->next)
18524       (lookup *(eax+8) *(eax+0xc))  # List-next, List-next => eax
18525       #
18526       eb/jump loop/disp8
18527     }
18528     # edi = out
18529     8b/-> *(ebp+0x1c) 7/r32/edi
18530     # curr->next = out
18531     8b/-> *edi 1/r32/ecx
18532     89/<- *(eax+8) 1/r32/ecx  # List-next
18533     8b/-> *(edi+4) 1/r32/ecx
18534     89/<- *(eax+0xc) 1/r32/ecx  # List-next
18535     # out = list
18536     8b/-> *(ebp+0x14) 1/r32/ecx
18537     89/<- *edi 1/r32/ecx
18538     8b/-> *(ebp+0x18) 1/r32/ecx
18539     89/<- *(edi+4) 1/r32/ecx
18540 $append-list:end:
18541     # . restore registers
18542     5f/pop-to-edi
18543     59/pop-to-ecx
18544     58/pop-to-eax
18545     # . epilogue
18546     89/<- %esp 5/r32/ebp
18547     5d/pop-to-ebp
18548     c3/return
18549 
18550 append-stmt-var:  # ad: (addr allocation-descriptor), v: (handle var), vars: (handle stmt-var), is-deref?: boolean, out: (addr handle stmt-var)
18551     # . prologue
18552     55/push-ebp
18553     89/<- %ebp 4/r32/esp
18554     # . save registers
18555     50/push-eax
18556     51/push-ecx
18557     57/push-edi
18558     # edi = out
18559     8b/-> *(ebp+0x20) 7/r32/edi
18560     # out = new stmt-var
18561     (allocate *(ebp+8) *Stmt-var-size %edi)
18562     # var out-addr/ecx: (addr stmt-var) = lookup(*out)
18563     (lookup *edi *(edi+4))  # => eax
18564     89/<- %ecx 0/r32/eax
18565     # out-addr->value = v
18566     8b/-> *(ebp+0xc) 0/r32/eax
18567     89/<- *ecx 0/r32/eax  # Stmt-var-value
18568     8b/-> *(ebp+0x10) 0/r32/eax
18569     89/<- *(ecx+4) 0/r32/eax  # Stmt-var-value
18570     # out-addr->is-deref? = is-deref?
18571     8b/-> *(ebp+0x1c) 0/r32/eax
18572     89/<- *(ecx+0x10) 0/r32/eax  # Stmt-var-is-deref
18573     # if (vars == null) return result
18574     81 7/subop/compare *(ebp+0x14) 0/imm32/null
18575     74/jump-if-= $append-stmt-var:end/disp8
18576     # otherwise append
18577     # var curr/eax: (addr stmt-var) = lookup(vars)
18578     (lookup *(ebp+0x14) *(ebp+0x18))  # => eax
18579     # while (curr->next != null) curr = curr->next
18580     {
18581       81 7/subop/compare *(eax+8) 0/imm32  # Stmt-var-next
18582       74/jump-if-= break/disp8
18583       # curr = lookup(curr->next)
18584       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next, Stmt-var-next => eax
18585       #
18586       eb/jump loop/disp8
18587     }
18588     # curr->next = out
18589     8b/-> *edi 1/r32/ecx
18590     89/<- *(eax+8) 1/r32/ecx  # Stmt-var-next
18591     8b/-> *(edi+4) 1/r32/ecx
18592     89/<- *(eax+0xc) 1/r32/ecx  # Stmt-var-next
18593     # out = vars
18594     8b/-> *(ebp+0x14) 1/r32/ecx
18595     89/<- *edi 1/r32/ecx
18596     8b/-> *(ebp+0x18) 1/r32/ecx
18597     89/<- *(edi+4) 1/r32/ecx
18598 $append-stmt-var:end:
18599     # . restore registers
18600     5f/pop-to-edi
18601     59/pop-to-ecx
18602     58/pop-to-eax
18603     # . epilogue
18604     89/<- %esp 5/r32/ebp
18605     5d/pop-to-ebp
18606     c3/return
18607 
18608 append-to-block:  # ad: (addr allocation-descriptor), block: (addr block), x: (handle stmt)
18609     # . prologue
18610     55/push-ebp
18611     89/<- %ebp 4/r32/esp
18612     # . save registers
18613     50/push-eax
18614     56/push-esi
18615     # esi = block
18616     8b/-> *(ebp+0xc) 6/r32/esi
18617     # block->stmts = append(x, block->stmts)
18618     8d/copy-address *(esi+4) 0/r32/eax  # Block-stmts
18619     (append-list *(ebp+8)  *(ebp+0x10) *(ebp+0x14)  *(esi+4) *(esi+8)  %eax)  # ad, x, x, Block-stmts, Block-stmts
18620 $append-to-block:end:
18621     # . restore registers
18622     5e/pop-to-esi
18623     58/pop-to-eax
18624     # . epilogue
18625     89/<- %esp 5/r32/ebp
18626     5d/pop-to-ebp
18627     c3/return
18628 
18629 ## Parsing types
18630 # We need to create metadata on user-defined types, and we need to use this
18631 # metadata as we parse instructions.
18632 # However, we also want to allow types to be used before their definitions.
18633 # This means we can't ever assume any type data structures exist.
18634 
18635 lookup-or-create-constant:  # container: (addr stmt-var), field-name: (addr slice), out: (addr handle var)
18636     # . prologue
18637     55/push-ebp
18638     89/<- %ebp 4/r32/esp
18639     # . save registers
18640     50/push-eax
18641     56/push-esi
18642     # var container-type/esi: type-id
18643     (container-type *(ebp+8))  # => eax
18644     89/<- %esi 0/r32/eax
18645     # var tmp/eax: (handle typeinfo) = find-or-create-typeinfo(container-type)
18646     68/push 0/imm32
18647     68/push 0/imm32
18648     89/<- %eax 4/r32/esp
18649     (find-or-create-typeinfo %esi %eax)
18650     # var tmp-addr/eax: (addr typeinfo) = lookup(tmp)
18651     (lookup *eax *(eax+4))  # => eax
18652     # result = find-or-create-typeinfo-output-var(typeinfo, field-name)
18653 #?     (write-buffered Stderr "constant: ")
18654 #?     (write-slice-buffered Stderr *(ebp+0xc))
18655 #?     (write-buffered Stderr Newline)
18656 #?     (flush Stderr)
18657     (find-or-create-typeinfo-output-var %eax *(ebp+0xc) *(ebp+0x10))
18658 #?     8b/-> *(ebp+0x10) 0/r32/eax
18659 #?     (write-buffered Stderr "@")
18660 #?     (lookup *eax *(eax+4))
18661 #?     (write-int32-hex-buffered Stderr %eax)
18662 #?     (lookup *eax *(eax+4))
18663 #?     (write-buffered Stderr %eax)
18664 #?     (write-buffered Stderr Newline)
18665 #?     (flush Stderr)
18666 #?     (write-buffered Stderr "offset: ")
18667 #?     8b/-> *(eax+0x14) 0/r32/eax
18668 #?     (write-int32-hex-buffered Stderr %eax)
18669 #?     (write-buffered Stderr Newline)
18670 #?     (flush Stderr)
18671 $lookup-or-create-constant:end:
18672     # . reclaim locals
18673     81 0/subop/add %esp 8/imm32
18674     # . restore registers
18675     5e/pop-to-esi
18676     58/pop-to-eax
18677     # . epilogue
18678     89/<- %esp 5/r32/ebp
18679     5d/pop-to-ebp
18680     c3/return
18681 
18682 # if addr var:
18683 #   container->var->type->right->left->value
18684 # otherwise
18685 #   container->var->type->value
18686 container-type:  # container: (addr stmt-var) -> result/eax: type-id
18687     # . prologue
18688     55/push-ebp
18689     89/<- %ebp 4/r32/esp
18690     #
18691     8b/-> *(ebp+8) 0/r32/eax
18692     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
18693     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
18694     {
18695       81 7/subop/compare *(eax+8) 0/imm32  # Type-tree-right
18696       74/jump-if-= break/disp8
18697       (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
18698       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
18699     }
18700     8b/-> *(eax+4) 0/r32/eax  # Type-tree-value
18701 $container-type:end:
18702     # . epilogue
18703     89/<- %esp 5/r32/ebp
18704     5d/pop-to-ebp
18705     c3/return
18706 
18707 is-container?:  # t: type-id -> result/eax: boolean
18708     # . prologue
18709     55/push-ebp
18710     89/<- %ebp 4/r32/esp
18711     #
18712     8b/-> *(ebp+8) 0/r32/eax
18713     c1/shift 4/subop/left %eax 2/imm8
18714     3b/compare 0/r32/eax *Primitive-type-ids
18715     0f 9d/set-if->= %al
18716     81 4/subop/and %eax 0xff/imm32
18717 $is-container?:end:
18718     # . epilogue
18719     89/<- %esp 5/r32/ebp
18720     5d/pop-to-ebp
18721     c3/return
18722 
18723 find-or-create-typeinfo:  # t: type-id, out: (addr handle typeinfo)
18724     # . prologue
18725     55/push-ebp
18726     89/<- %ebp 4/r32/esp
18727     # . save registers
18728     50/push-eax
18729     51/push-ecx
18730     52/push-edx
18731     57/push-edi
18732     # edi = out
18733     8b/-> *(ebp+0xc) 7/r32/edi
18734     # var fields/ecx: (handle table (handle array byte) (handle typeinfo-entry))
18735     68/push 0/imm32
18736     68/push 0/imm32
18737     89/<- %ecx 4/r32/esp
18738     # find-typeinfo(t, out)
18739     (find-typeinfo *(ebp+8) %edi)
18740     {
18741       # if (*out != 0) break
18742       81 7/subop/compare *edi 0/imm32
18743       0f 85/jump-if-!= break/disp32
18744 $find-or-create-typeinfo:create:
18745       # *out = allocate
18746       (allocate Heap *Typeinfo-size %edi)
18747       # var tmp/eax: (addr typeinfo) = lookup(*out)
18748       (lookup *edi *(edi+4))  # => eax
18749 #?     (write-buffered Stderr "created typeinfo at ")
18750 #?     (write-int32-hex-buffered Stderr %eax)
18751 #?     (write-buffered Stderr " for type-id ")
18752 #?     (write-int32-hex-buffered Stderr *(ebp+8))
18753 #?     (write-buffered Stderr Newline)
18754 #?     (flush Stderr)
18755       # tmp->id = t
18756       8b/-> *(ebp+8) 2/r32/edx
18757       89/<- *eax 2/r32/edx  # Typeinfo-id
18758       # tmp->fields = new table
18759       # . fields = new table
18760       (new-stream Heap 0x40 *Typeinfo-fields-row-size %ecx)
18761       # . tmp->fields = fields
18762       8b/-> *ecx 2/r32/edx
18763       89/<- *(eax+4) 2/r32/edx  # Typeinfo-fields
18764       8b/-> *(ecx+4) 2/r32/edx
18765       89/<- *(eax+8) 2/r32/edx  # Typeinfo-fields
18766       # tmp->next = Program->types
18767       8b/-> *_Program-types 1/r32/ecx
18768       89/<- *(eax+0x10) 1/r32/ecx  # Typeinfo-next
18769       8b/-> *_Program-types->payload 1/r32/ecx
18770       89/<- *(eax+0x14) 1/r32/ecx  # Typeinfo-next
18771       # Program->types = out
18772       8b/-> *edi 1/r32/ecx
18773       89/<- *_Program-types 1/r32/ecx
18774       8b/-> *(edi+4) 1/r32/ecx
18775       89/<- *_Program-types->payload 1/r32/ecx
18776     }
18777 $find-or-create-typeinfo:end:
18778     # . reclaim locals
18779     81 0/subop/add %esp 8/imm32
18780     # . restore registers
18781     5f/pop-to-edi
18782     5a/pop-to-edx
18783     59/pop-to-ecx
18784     58/pop-to-eax
18785     # . epilogue
18786     89/<- %esp 5/r32/ebp
18787     5d/pop-to-ebp
18788     c3/return
18789 
18790 find-typeinfo:  # t: type-id, out: (addr handle typeinfo)
18791     # . prologue
18792     55/push-ebp
18793     89/<- %ebp 4/r32/esp
18794     # . save registers
18795     50/push-eax
18796     51/push-ecx
18797     52/push-edx
18798     57/push-edi
18799     # ecx = t
18800     8b/-> *(ebp+8) 1/r32/ecx
18801     # edi = out
18802     8b/-> *(ebp+0xc) 7/r32/edi
18803     # *out = Program->types
18804     8b/-> *_Program-types 0/r32/eax
18805     89/<- *edi 0/r32/eax
18806     8b/-> *_Program-types->payload 0/r32/eax
18807     89/<- *(edi+4) 0/r32/eax
18808     {
18809 $find-typeinfo:loop:
18810       # if (*out == 0) break
18811       81 7/subop/compare *edi 0/imm32
18812       74/jump-if-= break/disp8
18813 $find-typeinfo:check:
18814       # var tmp/eax: (addr typeinfo) = lookup(*out)
18815       (lookup *edi *(edi+4))  # => eax
18816       # if (tmp->id == t) break
18817       39/compare *eax 1/r32/ecx  # Typeinfo-id
18818       74/jump-if-= break/disp8
18819 $find-typeinfo:continue:
18820       # *out = tmp->next
18821       8b/-> *(eax+0x10) 2/r32/edx  # Typeinfo-next
18822       89/<- *edi 2/r32/edx
18823       8b/-> *(eax+0x14) 2/r32/edx  # Typeinfo-next
18824       89/<- *(edi+4) 2/r32/edx
18825       #
18826       eb/jump loop/disp8
18827     }
18828 $find-typeinfo:end:
18829     # . restore registers
18830     5f/pop-to-edi
18831     5a/pop-to-edx
18832     59/pop-to-ecx
18833     58/pop-to-eax
18834     # . epilogue
18835     89/<- %esp 5/r32/ebp
18836     5d/pop-to-ebp
18837     c3/return
18838 
18839 find-or-create-typeinfo-output-var:  # T: (addr typeinfo), f: (addr slice), out: (addr handle var)
18840     # . prologue
18841     55/push-ebp
18842     89/<- %ebp 4/r32/esp
18843     # . save registers
18844     50/push-eax
18845     52/push-edx
18846     57/push-edi
18847     # var dest/edi: (handle typeinfo-entry)
18848     68/push 0/imm32
18849     68/push 0/imm32
18850     89/<- %edi 4/r32/esp
18851     # find-or-create-typeinfo-fields(T, f, dest)
18852     (find-or-create-typeinfo-fields *(ebp+8) *(ebp+0xc) %edi)
18853     # var dest-addr/edi: (addr typeinfo-entry) = lookup(dest)
18854     (lookup *edi *(edi+4))  # => eax
18855     89/<- %edi 0/r32/eax
18856     # if dest-addr->output-var doesn't exist, create it
18857     {
18858       81 7/subop/compare *(edi+0xc) 0/imm32  # Typeinfo-entry-output-var
18859       0f 85/jump-if-!= break/disp32
18860       # dest-addr->output-var = new var(dummy name, type, -1 offset)
18861       # . var name/eax: (handle array byte) = "field"
18862       68/push 0/imm32
18863       68/push 0/imm32
18864       89/<- %eax 4/r32/esp
18865       (slice-to-string Heap *(ebp+0xc) %eax)
18866       # . new var
18867       8d/copy-address *(edi+0xc) 2/r32/edx
18868       (new-var Heap  *eax *(eax+4)  %edx)
18869       # . reclaim name
18870       81 0/subop/add %esp 8/imm32
18871       # var result/edx: (addr var) = lookup(dest-addr->output-var)
18872       (lookup *(edi+0xc) *(edi+0x10))  # => eax
18873       89/<- %edx 0/r32/eax
18874       # result->type = new constant type
18875       8d/copy-address *(edx+8) 0/r32/eax  # Var-type
18876       (allocate Heap *Type-tree-size %eax)
18877       (lookup *(edx+8) *(edx+0xc))  # => eax
18878       c7 0/subop/copy *eax 1/imm32/true  # Type-tree-is-atom
18879       c7 0/subop/copy *(eax+4) 6/imm32/constant  # Type-tree-value
18880       c7 0/subop/copy *(eax+8) 0/imm32  # Type-tree-left
18881       c7 0/subop/copy *(eax+0xc) 0/imm32  # Type-tree-right
18882       c7 0/subop/copy *(eax+0x10) 0/imm32  # Type-tree-right
18883       # result->offset isn't filled out yet
18884       c7 0/subop/copy *(edx+0x14) -1/imm32/uninitialized  # Var-offset
18885     }
18886     # out = dest-addr->output-var
18887     8b/-> *(ebp+0x10) 2/r32/edx
18888     8b/-> *(edi+0xc) 0/r32/eax  # Typeinfo-entry-output-var
18889     89/<- *edx 0/r32/eax
18890     8b/-> *(edi+0x10) 0/r32/eax  # Typeinfo-entry-output-var
18891     89/<- *(edx+4) 0/r32/eax
18892 $find-or-create-typeinfo-output-var:end:
18893     # . reclaim locals
18894     81 0/subop/add %esp 8/imm32
18895     # . restore registers
18896     5f/pop-to-edi
18897     5a/pop-to-edx
18898     58/pop-to-eax
18899     # . epilogue
18900     89/<- %esp 5/r32/ebp
18901     5d/pop-to-ebp
18902     c3/return
18903 
18904 find-or-create-typeinfo-fields:  # T: (addr typeinfo), f: (addr slice), out: (addr handle typeinfo-entry)
18905     # . prologue
18906     55/push-ebp
18907     89/<- %ebp 4/r32/esp
18908     # . save registers
18909     50/push-eax
18910     56/push-esi
18911     57/push-edi
18912     # eax = lookup(T->fields)
18913     8b/-> *(ebp+8) 0/r32/eax
18914     (lookup *(eax+4) *(eax+8))  # Typeinfo-fields Typeinfo-fields => eax
18915     # edi = out
18916     8b/-> *(ebp+0x10) 7/r32/edi
18917     # var src/esi: (addr handle typeinfo-entry) = get-or-insert-slice(T->fields, f)
18918     (get-or-insert-slice %eax *(ebp+0xc) *Typeinfo-fields-row-size Heap)  # => eax
18919     89/<- %esi 0/r32/eax
18920     # if src doesn't exist, allocate it
18921     {
18922       81 7/subop/compare *esi 0/imm32
18923       75/jump-if-!= break/disp8
18924       (allocate Heap *Typeinfo-entry-size %esi)
18925 #?       (write-buffered Stderr "handle at ")
18926 #?       (write-int32-hex-buffered Stderr %esi)
18927 #?       (write-buffered Stderr ": ")
18928 #?       (write-int32-hex-buffered Stderr *esi)
18929 #?       (write-buffered Stderr " ")
18930 #?       (write-int32-hex-buffered Stderr *(esi+4))
18931 #?       (write-buffered Stderr Newline)
18932 #?       (flush Stderr)
18933 #?       (lookup *esi *(esi+4))
18934 #?       (write-buffered Stderr "created typeinfo fields at ")
18935 #?       (write-int32-hex-buffered Stderr %esi)
18936 #?       (write-buffered Stderr " for ")
18937 #?       (write-int32-hex-buffered Stderr *(ebp+8))
18938 #?       (write-buffered Stderr Newline)
18939 #?       (flush Stderr)
18940     }
18941     # *out = src
18942     # . *edi = *src
18943     8b/-> *esi 0/r32/eax
18944     89/<- *edi 0/r32/eax
18945     8b/-> *(esi+4) 0/r32/eax
18946     89/<- *(edi+4) 0/r32/eax
18947 $find-or-create-typeinfo-fields:end:
18948     # . restore registers
18949     5f/pop-to-edi
18950     5e/pop-to-esi
18951     58/pop-to-eax
18952     # . epilogue
18953     89/<- %esp 5/r32/ebp
18954     5d/pop-to-ebp
18955     c3/return
18956 
18957 populate-mu-type:  # in: (addr stream byte), t: (addr typeinfo), err: (addr buffered-file), ed: (addr exit-descriptor)
18958     # pseudocode:
18959     #   var line: (stream byte 512)
18960     #   curr-index = 0
18961     #   while true
18962     #     clear-stream(line)
18963     #     read-line-buffered(in, line)
18964     #     if line->write == 0
18965     #       abort
18966     #     word-slice = next-mu-token(line)
18967     #     if slice-empty?(word-slice)               # end of line
18968     #       continue
18969     #     if slice-equal?(word-slice, "}")
18970     #       break
18971     #     var v: (handle var) = parse-var-with-type(word-slice, line)
18972     #     var r: (handle typeinfo-fields) = find-or-create-typeinfo-fields(t, word-slice/v->name)
18973     #     TODO: ensure that r->first is null
18974     #     r->index = curr-index
18975     #     curr-index++
18976     #     r->input-var = v
18977     #     if r->output-var == 0
18978     #       r->output-var = new literal
18979     #     TODO: ensure nothing else in line
18980     # t->total-size-in-bytes = -2 (not yet initialized)
18981     #
18982     # . prologue
18983     55/push-ebp
18984     89/<- %ebp 4/r32/esp
18985     # var curr-index: int at *(ebp-4)
18986     68/push 0/imm32
18987     # . save registers
18988     50/push-eax
18989     51/push-ecx
18990     52/push-edx
18991     53/push-ebx
18992     56/push-esi
18993     57/push-edi
18994     # edi = t
18995     8b/-> *(ebp+0xc) 7/r32/edi
18996     # var line/ecx: (stream byte 512)
18997     81 5/subop/subtract %esp 0x200/imm32
18998     68/push 0x200/imm32/size
18999     68/push 0/imm32/read
19000     68/push 0/imm32/write
19001     89/<- %ecx 4/r32/esp
19002     # var word-slice/edx: slice
19003     68/push 0/imm32/end
19004     68/push 0/imm32/start
19005     89/<- %edx 4/r32/esp
19006     # var v/esi: (handle var)
19007     68/push 0/imm32
19008     68/push 0/imm32
19009     89/<- %esi 4/r32/esp
19010     # var r/ebx: (handle typeinfo-entry)
19011     68/push 0/imm32
19012     68/push 0/imm32
19013     89/<- %ebx 4/r32/esp
19014     {
19015 $populate-mu-type:line-loop:
19016       (clear-stream %ecx)
19017       (read-line-buffered *(ebp+8) %ecx)
19018       # if (line->write == 0) abort
19019       81 7/subop/compare *ecx 0/imm32
19020       0f 84/jump-if-= $populate-mu-type:error1/disp32
19021 +--  6 lines: #?       # dump line ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
19027       (next-mu-token %ecx %edx)
19028       # if slice-empty?(word-slice) continue
19029       (slice-empty? %edx)  # => eax
19030       3d/compare-eax-and 0/imm32
19031       0f 85/jump-if-!= loop/disp32
19032       # if slice-equal?(word-slice, "}") break
19033       (slice-equal? %edx "}")
19034       3d/compare-eax-and 0/imm32
19035       0f 85/jump-if-!= break/disp32
19036 $populate-mu-type:parse-element:
19037       # v = parse-var-with-type(word-slice, first-line)
19038       # must do this first to strip the trailing ':' from word-slice before
19039       # using it in find-or-create-typeinfo-fields below
19040       # TODO: clean up that mutation in parse-var-with-type
19041       (type-name *edi)  # Typeinfo-id => eax
19042       (parse-var-with-type %edx %ecx %esi %eax *(ebp+0x10) *(ebp+0x14))
19043       # if v is an addr, abort
19044       (lookup *esi *(esi+4))  # => eax
19045       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
19046       (is-mu-addr-type? %eax)  # => eax
19047       3d/compare-eax-and 0/imm32/false
19048       0f 85/jump-if-!= $populate-mu-type:error2/disp32
19049       # if v is an array, abort  (we could support it, but initialization gets complex)
19050       (lookup *esi *(esi+4))  # => eax
19051       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
19052       (is-mu-array-type? %eax)  # => eax
19053       3d/compare-eax-and 0/imm32/false
19054       0f 85/jump-if-!= $populate-mu-type:error3/disp32
19055       # if v is a byte, abort
19056       (lookup *esi *(esi+4))  # => eax
19057       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
19058       (is-simple-mu-type? %eax 8)  # byte => eax
19059       3d/compare-eax-and 0/imm32/false
19060       0f 85/jump-if-!= $populate-mu-type:error4/disp32
19061       # if v is a slice, abort
19062       (lookup *esi *(esi+4))  # => eax
19063       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
19064       (is-simple-mu-type? %eax 0xc)  # slice => eax
19065       3d/compare-eax-and 0/imm32/false
19066       0f 85/jump-if-!= $populate-mu-type:error5/disp32
19067       # if v is a stream, abort  (we could support it, but initialization gets even more complex)
19068       (lookup *esi *(esi+4))  # => eax
19069       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
19070       (is-mu-stream-type? %eax)  # => eax
19071       3d/compare-eax-and 0/imm32/false
19072       0f 85/jump-if-!= $populate-mu-type:error6/disp32
19073       # var tmp/ecx
19074       51/push-ecx
19075 $populate-mu-type:create-typeinfo-fields:
19076       # var r/ebx: (handle typeinfo-entry)
19077       (find-or-create-typeinfo-fields %edi %edx %ebx)
19078       # r->index = curr-index
19079       (lookup *ebx *(ebx+4))  # => eax
19080       8b/-> *(ebp-4) 1/r32/ecx
19081 #?       (write-buffered Stderr "saving index ")
19082 #?       (write-int32-hex-buffered Stderr %ecx)
19083 #?       (write-buffered Stderr " at ")
19084 #?       (write-int32-hex-buffered Stderr %edi)
19085 #?       (write-buffered Stderr Newline)
19086 #?       (flush Stderr)
19087       89/<- *(eax+8) 1/r32/ecx  # Typeinfo-entry-index
19088       # ++curr-index
19089       ff 0/subop/increment *(ebp-4)
19090 $populate-mu-type:set-input-type:
19091       # r->input-var = v
19092       8b/-> *esi 1/r32/ecx
19093       89/<- *eax 1/r32/ecx  # Typeinfo-entry-input-var
19094       8b/-> *(esi+4) 1/r32/ecx
19095       89/<- *(eax+4) 1/r32/ecx  # Typeinfo-entry-input-var
19096       # restore line
19097       59/pop-to-ecx
19098       {
19099 $populate-mu-type:create-output-type:
19100         # if (r->output-var == 0) create a new var with some placeholder data
19101         81 7/subop/compare *(eax+0xc) 0/imm32  # Typeinfo-entry-output-var
19102         75/jump-if-!= break/disp8
19103         8d/copy-address *(eax+0xc) 0/r32/eax  # Typeinfo-entry-output-var
19104         (new-literal Heap %edx %eax)
19105       }
19106       e9/jump loop/disp32
19107     }
19108 $populate-mu-type:invalidate-total-size-in-bytes:
19109     # Offsets and total size may not be accurate here since we may not yet
19110     # have encountered the element types.
19111     # We'll recompute them separately after parsing the entire program.
19112     c7 0/subop/copy *(edi+0xc) -2/imm32/uninitialized  # Typeinfo-total-size-in-bytes
19113 $populate-mu-type:end:
19114     # . reclaim locals
19115     81 0/subop/add %esp 0x224/imm32
19116     # . restore registers
19117     5f/pop-to-edi
19118     5e/pop-to-esi
19119     5b/pop-to-ebx
19120     5a/pop-to-edx
19121     59/pop-to-ecx
19122     58/pop-to-eax
19123     # reclaim curr-index
19124     81 0/subop/add %esp 4/imm32
19125     # . epilogue
19126     89/<- %esp 5/r32/ebp
19127     5d/pop-to-ebp
19128     c3/return
19129 
19130 $populate-mu-type:error1:
19131     # error("incomplete type definition '" t->name "'\n")
19132     (write-buffered *(ebp+0x10) "incomplete type definition '")
19133     (type-name *edi)  # Typeinfo-id => eax
19134     (write-buffered *(ebp+0x10) %eax)
19135     (write-buffered *(ebp+0x10) "\n")
19136     (flush *(ebp+0x10))
19137     (stop *(ebp+0x14) 1)
19138     # never gets here
19139 
19140 $populate-mu-type:error2:
19141     (write-buffered *(ebp+0x10) "type ")
19142     (type-name *edi)  # Typeinfo-id => eax
19143     (write-buffered *(ebp+0x10) %eax)
19144     (write-buffered *(ebp+0x10) ": 'addr' elements not allowed\n")
19145     (flush *(ebp+0x10))
19146     (stop *(ebp+0x14) 1)
19147     # never gets here
19148 
19149 $populate-mu-type:error3:
19150     (write-buffered *(ebp+0x10) "type ")
19151     (type-name *edi)  # Typeinfo-id => eax
19152     (write-buffered *(ebp+0x10) %eax)
19153     (write-buffered *(ebp+0x10) ": 'array' elements not allowed for now\n")
19154     (flush *(ebp+0x10))
19155     (stop *(ebp+0x14) 1)
19156     # never gets here
19157 
19158 $populate-mu-type:error4:
19159     (write-buffered *(ebp+0x10) "type ")
19160     (type-name *edi)  # Typeinfo-id => eax
19161     (write-buffered *(ebp+0x10) %eax)
19162     (write-buffered *(ebp+0x10) ": 'byte' elements not allowed\n")
19163     (flush *(ebp+0x10))
19164     (stop *(ebp+0x14) 1)
19165     # never gets here
19166 
19167 $populate-mu-type:error5:
19168     (write-buffered *(ebp+0x10) "type ")
19169     (type-name *edi)  # Typeinfo-id => eax
19170     (write-buffered *(ebp+0x10) %eax)
19171     (write-buffered *(ebp+0x10) ": 'slice' elements not allowed\n")
19172     (flush *(ebp+0x10))
19173     (stop *(ebp+0x14) 1)
19174     # never gets here
19175 
19176 $populate-mu-type:error6:
19177     (write-buffered *(ebp+0x10) "type ")
19178     (type-name *edi)  # Typeinfo-id => eax
19179     (write-buffered *(ebp+0x10) %eax)
19180     (write-buffered *(ebp+0x10) ": 'stream' elements not allowed for now\n")
19181     (flush *(ebp+0x10))
19182     (stop *(ebp+0x14) 1)
19183     # never gets here
19184 
19185 type-name:  # index: int -> result/eax: (addr array byte)
19186     # . prologue
19187     55/push-ebp
19188     89/<- %ebp 4/r32/esp
19189     #
19190     (index Type-id *(ebp+8))
19191 $type-name:end:
19192     # . epilogue
19193     89/<- %esp 5/r32/ebp
19194     5d/pop-to-ebp
19195     c3/return
19196 
19197 index:  # arr: (addr stream (handle array byte)), index: int -> result/eax: (addr array byte)
19198     # . prologue
19199     55/push-ebp
19200     89/<- %ebp 4/r32/esp
19201     # . save registers
19202     56/push-esi
19203     # TODO: bounds-check index
19204     # esi = arr
19205     8b/-> *(ebp+8) 6/r32/esi
19206     # eax = index
19207     8b/-> *(ebp+0xc) 0/r32/eax
19208     # eax = *(arr + 12 + index)
19209     8b/-> *(esi+eax<<2+0xc) 0/r32/eax
19210 $index:end:
19211     # . restore registers
19212     5e/pop-to-esi
19213     # . epilogue
19214     89/<- %esp 5/r32/ebp
19215     5d/pop-to-ebp
19216     c3/return
19217 
19218 #######################################################
19219 # Compute type sizes
19220 #######################################################
19221 
19222 # Compute the sizes of all user-defined types.
19223 # We'll need the sizes of their elements, which may be other user-defined
19224 # types, which we will compute as needed.
19225 
19226 # Initially, all user-defined types have their sizes set to -2 (invalid)
19227 populate-mu-type-sizes:  # err: (addr buffered-file), ed: (addr exit-descriptor)
19228     # . prologue
19229     55/push-ebp
19230     89/<- %ebp 4/r32/esp
19231 $populate-mu-type-sizes:total-sizes:
19232     # var curr/eax: (addr typeinfo) = lookup(Program->types)
19233     (lookup *_Program-types *_Program-types->payload)  # => eax
19234     {
19235       # if (curr == null) break
19236       3d/compare-eax-and 0/imm32/null
19237       74/jump-if-= break/disp8
19238       (populate-mu-type-sizes-in-type %eax *(ebp+8) *(ebp+0xc))
19239       # curr = lookup(curr->next)
19240       (lookup *(eax+0x10) *(eax+0x14))  # Typeinfo-next Typeinfo-next => eax
19241       eb/jump loop/disp8
19242     }
19243 $populate-mu-type-sizes:offsets:
19244     # curr = *Program->types
19245     (lookup *_Program-types *_Program-types->payload)  # => eax
19246     {
19247       # if (curr == null) break
19248       3d/compare-eax-and 0/imm32/null
19249       74/jump-if-= break/disp8
19250       (populate-mu-type-offsets %eax *(ebp+8) *(ebp+0xc))
19251       # curr = curr->next
19252       (lookup *(eax+0x10) *(eax+0x14))  # Typeinfo-next Typeinfo-next => eax
19253       eb/jump loop/disp8
19254     }
19255 $populate-mu-type-sizes:end:
19256     # . epilogue
19257     89/<- %esp 5/r32/ebp
19258     5d/pop-to-ebp
19259     c3/return
19260 
19261 # compute sizes of all fields, recursing as necessary
19262 # sum up all their sizes to arrive at total size
19263 # fields may be out of order, but that doesn't affect the answer
19264 populate-mu-type-sizes-in-type:  # T: (addr typeinfo), err: (addr buffered-file), ed: (addr exit-descriptor)
19265     # . prologue
19266     55/push-ebp
19267     89/<- %ebp 4/r32/esp
19268     # . save registers
19269     50/push-eax
19270     51/push-ecx
19271     52/push-edx
19272     56/push-esi
19273     57/push-edi
19274     # esi = T
19275     8b/-> *(ebp+8) 6/r32/esi
19276     # if T is already computed, return
19277     81 7/subop/compare *(esi+0xc) 0/imm32  # Typeinfo-total-size-in-bytes
19278     0f 8d/jump-if->= $populate-mu-type-sizes-in-type:end/disp32
19279     # if T is being computed, abort
19280     81 7/subop/compare *(esi+0xc) -1/imm32/being-computed  # Typeinfo-total-size-in-bytes
19281     0f 84/jump-if-= $populate-mu-type-sizes-in-type:abort/disp32
19282     # tag T (-2 to -1) to avoid infinite recursion
19283     c7 0/subop/copy *(esi+0xc) -1/imm32/being-computed  # Typeinfo-total-size-in-bytes
19284     # var total-size/edi: int = 0
19285     bf/copy-to-edi 0/imm32
19286     # - for every field, if it's a user-defined type, compute its size
19287     # var table/ecx: (addr table (handle array byte) (handle typeinfo-entry)) = lookup(T->fields)
19288     (lookup *(esi+4) *(esi+8))  # Typeinfo-fields Typeinfo-fields => eax
19289     89/<- %ecx 0/r32/eax
19290     # var table-size/edx: int = table->write
19291     8b/-> *ecx 2/r32/edx  # stream-write
19292     # var curr/ecx: (addr table_row) = table->data
19293     8d/copy-address *(ecx+0xc) 1/r32/ecx
19294     # var max/edx: (addr table_row) = table->data + table->write
19295     8d/copy-address *(ecx+edx) 2/r32/edx
19296     {
19297 $populate-mu-type-sizes-in-type:loop:
19298       # if (curr >= max) break
19299       39/compare %ecx 2/r32/edx
19300       73/jump-if-addr>= break/disp8
19301       # var t/eax: (addr typeinfo-entry) = lookup(curr->value)
19302       (lookup *(ecx+8) *(ecx+0xc))  # => eax
19303       # if (t->input-var == 0) silently ignore it; we'll emit a nice error message while type-checking
19304       81 7/subop/compare *eax 0/imm32  # Typeinfo-entry-input-var
19305       74/jump-if-= $populate-mu-type-sizes-in-type:end/disp8
19306       # compute size of t->input-var
19307       (lookup *eax *(eax+4))  # Typeinfo-entry-input-var Typeinfo-entry-input-var => eax
19308       (compute-size-of-var %eax *(ebp+0xc) *(ebp+0x10))  # => eax
19309       # result += eax
19310       01/add-to %edi 0/r32/eax
19311       # curr += row-size
19312       81 0/subop/add %ecx 0x10/imm32  # Typeinfo-fields-row-size
19313       #
19314       eb/jump loop/disp8
19315     }
19316     # - save result
19317     89/<- *(esi+0xc) 7/r32/edi  # Typeinfo-total-size-in-bytes
19318 $populate-mu-type-sizes-in-type:end:
19319     # . restore registers
19320     5f/pop-to-edi
19321     5e/pop-to-esi
19322     5a/pop-to-edx
19323     59/pop-to-ecx
19324     58/pop-to-eax
19325     # . epilogue
19326     89/<- %esp 5/r32/ebp
19327     5d/pop-to-ebp
19328     c3/return
19329 
19330 $populate-mu-type-sizes-in-type:abort:
19331     (write-buffered *(ebp+0xc) "cycle in type definitions\n")
19332     (flush *(ebp+0xc))
19333     (stop *(ebp+0x10) 1)
19334     # never gets here
19335 
19336 # Analogous to size-of, except we need to compute what size-of can just read
19337 # off the right data structures.
19338 compute-size-of-var:  # in: (addr var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
19339     # . prologue
19340     55/push-ebp
19341     89/<- %ebp 4/r32/esp
19342     # . push registers
19343     51/push-ecx
19344     # var t/ecx: (addr type-tree) = lookup(v->type)
19345     8b/-> *(ebp+8) 1/r32/ecx
19346     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
19347     89/<- %ecx 0/r32/eax
19348     # if (t->is-atom == false) t = lookup(t->left)
19349     {
19350       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
19351       75/jump-if-!= break/disp8
19352       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
19353       89/<- %ecx 0/r32/eax
19354     }
19355     # TODO: ensure t is an atom
19356     (compute-size-of-type-id *(ecx+4) *(ebp+0xc) *(ebp+0x10))  # Type-tree-value => eax
19357 $compute-size-of-var:end:
19358     # . restore registers
19359     59/pop-to-ecx
19360     # . epilogue
19361     89/<- %esp 5/r32/ebp
19362     5d/pop-to-ebp
19363     c3/return
19364 
19365 compute-size-of-type-id:  # t: type-id, err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
19366     # . prologue
19367     55/push-ebp
19368     89/<- %ebp 4/r32/esp
19369     # . save registers
19370     51/push-ecx
19371     # var out/ecx: (handle typeinfo)
19372     68/push 0/imm32
19373     68/push 0/imm32
19374     89/<- %ecx 4/r32/esp
19375     # eax = t
19376     8b/-> *(ebp+8) 0/r32/eax
19377     # if t is a literal, return 0
19378     3d/compare-eax-and 0/imm32/literal
19379     0f 84/jump-if-= $compute-size-of-type-id:end/disp32  # eax changes type from type-id to int
19380     # if t is a byte, return 4 (because we don't really support non-multiples of 4)
19381     3d/compare-eax-and 8/imm32/byte
19382     {
19383       75/jump-if-!= break/disp8
19384       b8/copy-to-eax 4/imm32
19385       eb/jump $compute-size-of-type-id:end/disp8
19386     }
19387     # if t is a handle, return 8
19388     3d/compare-eax-and 4/imm32/handle
19389     {
19390       75/jump-if-!= break/disp8
19391       b8/copy-to-eax 8/imm32
19392       eb/jump $compute-size-of-type-id:end/disp8  # eax changes type from type-id to int
19393     }
19394     # if t is a slice, return 8
19395     3d/compare-eax-and 0xc/imm32/slice
19396     {
19397       75/jump-if-!= break/disp8
19398       b8/copy-to-eax 8/imm32
19399       eb/jump $compute-size-of-type-id:end/disp8  # eax changes type from type-id to int
19400     }
19401     # if t is a user-defined type, compute its size
19402     # TODO: support non-atom type
19403     (find-typeinfo %eax %ecx)
19404     {
19405       81 7/subop/compare *ecx 0/imm32
19406       74/jump-if-= break/disp8
19407 $compute-size-of-type-id:user-defined:
19408       (lookup *ecx *(ecx+4))  # => eax
19409       (populate-mu-type-sizes-in-type %eax *(ebp+0xc) *(ebp+0x10))
19410       8b/-> *(eax+0xc) 0/r32/eax  # Typeinfo-total-size-in-bytes
19411       eb/jump $compute-size-of-type-id:end/disp8
19412     }
19413     # otherwise return the word size
19414     b8/copy-to-eax 4/imm32
19415 $compute-size-of-type-id:end:
19416     # . reclaim locals
19417     81 0/subop/add %esp 8/imm32
19418     # . restore registers
19419     59/pop-to-ecx
19420     # . epilogue
19421     89/<- %esp 5/r32/ebp
19422     5d/pop-to-ebp
19423     c3/return
19424 
19425 # at this point we have total sizes for all user-defined types
19426 # compute offsets for each element
19427 # complication: fields may be out of order
19428 populate-mu-type-offsets:  # in: (addr typeinfo), err: (addr buffered-file), ed: (addr exit-descriptor)
19429     # . prologue
19430     55/push-ebp
19431     89/<- %ebp 4/r32/esp
19432     # . save registers
19433     50/push-eax
19434     51/push-ecx
19435     52/push-edx
19436     53/push-ebx
19437     56/push-esi
19438     57/push-edi
19439 #?     (dump-typeinfos "aaa\n")
19440     # var curr-offset/edi: int = 0
19441     bf/copy-to-edi 0/imm32
19442     # var table/ecx: (addr table string_key (handle typeinfo-entry)) = lookup(in->fields)
19443     8b/-> *(ebp+8) 1/r32/ecx
19444     (lookup *(ecx+4) *(ecx+8))  # Typeinfo-fields Typeinfo-fields => eax
19445     89/<- %ecx 0/r32/eax
19446     # var num-elems/edx: int = table->write / Typeinfo-fields-row-size
19447     8b/-> *ecx 2/r32/edx  # stream-write
19448     c1 5/subop/shift-right-logical  %edx 4/imm8
19449     # var i/ebx: int = 0
19450     bb/copy-to-ebx 0/imm32
19451     {
19452 $populate-mu-type-offsets:loop:
19453       39/compare %ebx 2/r32/edx
19454       0f 8d/jump-if->= break/disp32
19455 #?       (write-buffered Stderr "looking up index ")
19456 #?       (write-int32-hex-buffered Stderr %ebx)
19457 #?       (write-buffered Stderr " in ")
19458 #?       (write-int32-hex-buffered Stderr *(ebp+8))
19459 #?       (write-buffered Stderr Newline)
19460 #?       (flush Stderr)
19461       # var v/esi: (addr typeinfo-entry)
19462       (locate-typeinfo-entry-with-index %ecx %ebx *(ebp+0xc) *(ebp+0x10))  # => eax
19463       89/<- %esi 0/r32/eax
19464       # if v is null, silently move on; we'll emit a nice error message while type-checking
19465       81 7/subop/compare %esi 0/imm32  # Typeinfo-entry-input-var
19466       74/jump-if-= $populate-mu-type-offsets:end/disp8
19467       # if (v->input-var == 0) silently ignore v; we'll emit a nice error message while type-checking
19468       81 7/subop/compare *esi 0/imm32  # Typeinfo-entry-input-var
19469       74/jump-if-= $populate-mu-type-offsets:end/disp8
19470       # v->output-var->offset = curr-offset
19471       # . eax: (addr var)
19472       (lookup *(esi+0xc) *(esi+0x10))  # Typeinfo-entry-output-var Typeinfo-entry-output-var => eax
19473       89/<- *(eax+0x14) 7/r32/edi  # Var-offset
19474       # curr-offset += size-of(v->input-var)
19475       (lookup *esi *(esi+4))  # Typeinfo-entry-input-var Typeinfo-entry-input-var => eax
19476       (size-of %eax)  # => eax
19477       01/add-to %edi 0/r32/eax
19478       # ++i
19479       43/increment-ebx
19480       e9/jump loop/disp32
19481     }
19482 $populate-mu-type-offsets:end:
19483     # . restore registers
19484     5f/pop-to-edi
19485     5e/pop-to-esi
19486     5b/pop-to-ebx
19487     5a/pop-to-edx
19488     59/pop-to-ecx
19489     58/pop-to-eax
19490     # . epilogue
19491     89/<- %esp 5/r32/ebp
19492     5d/pop-to-ebp
19493     c3/return
19494 
19495 locate-typeinfo-entry-with-index:  # table: (addr table (handle array byte) (handle typeinfo-entry)), idx: int, err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: (addr typeinfo-entry)
19496     # . prologue
19497     55/push-ebp
19498     89/<- %ebp 4/r32/esp
19499     # . save registers
19500     51/push-ecx
19501     52/push-edx
19502     53/push-ebx
19503     56/push-esi
19504     57/push-edi
19505     # esi = table
19506     8b/-> *(ebp+8) 6/r32/esi
19507     # var curr/ecx: (addr row (handle array byte) (handle typeinfo-entry)) = table->data
19508     8d/copy-address *(esi+0xc) 1/r32/ecx
19509     # var max/edx: (addr byte) = &table->data[table->write]
19510     8b/-> *esi 2/r32/edx
19511     8d/copy-address *(ecx+edx) 2/r32/edx
19512     {
19513 $locate-typeinfo-entry-with-index:loop:
19514       39/compare %ecx 2/r32/edx
19515       73/jump-if-addr>= break/disp8
19516       # var v/eax: (addr typeinfo-entry)
19517       (lookup *(ecx+8) *(ecx+0xc))  # => eax
19518       # if (v->index == idx) return v
19519       8b/-> *(eax+8) 3/r32/ebx  # Typeinfo-entry-index
19520 #?       (write-buffered Stderr "comparing ")
19521 #?       (write-int32-hex-buffered Stderr %ebx)
19522 #?       (write-buffered Stderr " and ")
19523 #?       (write-int32-hex-buffered Stderr *(ebp+0xc))
19524 #?       (write-buffered Stderr Newline)
19525 #?       (flush Stderr)
19526       39/compare *(ebp+0xc) 3/r32/ebx
19527       74/jump-if-= $locate-typeinfo-entry-with-index:end/disp8
19528       # curr += Typeinfo-entry-size
19529       81 0/subop/add %ecx 0x10/imm32  # Typeinfo-entry-size
19530       #
19531       eb/jump loop/disp8
19532     }
19533     # return 0
19534     b8/copy-to-eax 0/imm32
19535 $locate-typeinfo-entry-with-index:end:
19536 #?     (write-buffered Stderr "returning ")
19537 #?     (write-int32-hex-buffered Stderr %eax)
19538 #?     (write-buffered Stderr Newline)
19539 #?     (flush Stderr)
19540     # . restore registers
19541     5f/pop-to-edi
19542     5e/pop-to-esi
19543     5b/pop-to-ebx
19544     5a/pop-to-edx
19545     59/pop-to-ecx
19546     # . epilogue
19547     89/<- %esp 5/r32/ebp
19548     5d/pop-to-ebp
19549     c3/return
19550 
19551 dump-typeinfos:  # hdr: (addr array byte)
19552     # . prologue
19553     55/push-ebp
19554     89/<- %ebp 4/r32/esp
19555     # . save registers
19556     50/push-eax
19557     #
19558     (write-buffered Stderr *(ebp+8))
19559     (flush Stderr)
19560     # var curr/eax: (addr typeinfo) = lookup(Program->types)
19561     (lookup *_Program-types *_Program-types->payload)  # => eax
19562     {
19563       # if (curr == null) break
19564       3d/compare-eax-and 0/imm32
19565       74/jump-if-= break/disp8
19566       (write-buffered Stderr "---\n")
19567       (flush Stderr)
19568       (dump-typeinfo %eax)
19569       # curr = lookup(curr->next)
19570       (lookup *(eax+0x10) *(eax+0x14))  # Typeinfo-next Typeinfo-next => eax
19571       eb/jump loop/disp8
19572     }
19573 $dump-typeinfos:end:
19574     # . restore registers
19575     58/pop-to-eax
19576     # . epilogue
19577     89/<- %esp 5/r32/ebp
19578     5d/pop-to-ebp
19579     c3/return
19580 
19581 dump-typeinfo:  # in: (addr typeinfo)
19582     # . prologue
19583     55/push-ebp
19584     89/<- %ebp 4/r32/esp
19585     # . save registers
19586     50/push-eax
19587     51/push-ecx
19588     52/push-edx
19589     53/push-ebx
19590     56/push-esi
19591     57/push-edi
19592     # esi = in
19593     8b/-> *(ebp+8) 6/r32/esi
19594     # var table/ecx: (addr table (handle array byte) (handle typeinfo-entry)) = lookup(T->fields)
19595     (lookup *(esi+4) *(esi+8))  # Typeinfo-fields Typeinfo-fields => eax
19596     89/<- %ecx 0/r32/eax
19597     (write-buffered Stderr "id:")
19598     (write-int32-hex-buffered Stderr *esi)
19599     (write-buffered Stderr "\n")
19600     (write-buffered Stderr "fields @ ")
19601     (write-int32-hex-buffered Stderr %ecx)
19602     (write-buffered Stderr Newline)
19603     (flush Stderr)
19604     (write-buffered Stderr "  write: ")
19605     (write-int32-hex-buffered Stderr *ecx)
19606     (write-buffered Stderr Newline)
19607     (flush Stderr)
19608     (write-buffered Stderr "  read: ")
19609     (write-int32-hex-buffered Stderr *(ecx+4))
19610     (write-buffered Stderr Newline)
19611     (flush Stderr)
19612     (write-buffered Stderr "  size: ")
19613     (write-int32-hex-buffered Stderr *(ecx+8))
19614     (write-buffered Stderr Newline)
19615     (flush Stderr)
19616     # var table-size/edx: int = table->write
19617     8b/-> *ecx 2/r32/edx  # stream-write
19618     # var curr/ecx: (addr table_row) = table->data
19619     8d/copy-address *(ecx+0xc) 1/r32/ecx
19620     # var max/edx: (addr table_row) = table->data + table->write
19621     8d/copy-address *(ecx+edx) 2/r32/edx
19622     {
19623 $dump-typeinfo:loop:
19624       # if (curr >= max) break
19625       39/compare %ecx 2/r32/edx
19626       0f 83/jump-if-addr>= break/disp32
19627       (write-buffered Stderr "  row:\n")
19628       (write-buffered Stderr "    key: ")
19629       (write-int32-hex-buffered Stderr *ecx)
19630       (write-buffered Stderr ",")
19631       (write-int32-hex-buffered Stderr *(ecx+4))
19632       (write-buffered Stderr " = '")
19633       (lookup *ecx *(ecx+4))
19634       (write-buffered Stderr %eax)
19635       (write-buffered Stderr "' @ ")
19636       (write-int32-hex-buffered Stderr %eax)
19637       (write-buffered Stderr Newline)
19638       (flush Stderr)
19639       (write-buffered Stderr "    value: ")
19640       (write-int32-hex-buffered Stderr *(ecx+8))
19641       (write-buffered Stderr ",")
19642       (write-int32-hex-buffered Stderr *(ecx+0xc))
19643       (write-buffered Stderr " = typeinfo-entry@")
19644       (lookup *(ecx+8) *(ecx+0xc))
19645       (write-int32-hex-buffered Stderr %eax)
19646       (write-buffered Stderr Newline)
19647       (flush Stderr)
19648       (write-buffered Stderr "        input var@")
19649       (dump-var 5 %eax)
19650       (lookup *(ecx+8) *(ecx+0xc))
19651       (write-buffered Stderr "        index: ")
19652       (write-int32-hex-buffered Stderr *(eax+8))
19653       (write-buffered Stderr Newline)
19654       (flush Stderr)
19655       (write-buffered Stderr "        output var@")
19656       8d/copy-address *(eax+0xc) 0/r32/eax  # Typeinfo-entry-output-var
19657       (dump-var 5 %eax)
19658       (flush Stderr)
19659       # curr += row-size
19660       81 0/subop/add %ecx 0x10/imm32  # Typeinfo-fields-row-size
19661       #
19662       e9/jump loop/disp32
19663     }
19664 $dump-typeinfo:end:
19665     # . restore registers
19666     5f/pop-to-edi
19667     5e/pop-to-esi
19668     5b/pop-to-ebx
19669     5a/pop-to-edx
19670     59/pop-to-ecx
19671     58/pop-to-eax
19672     # . epilogue
19673     89/<- %esp 5/r32/ebp
19674     5d/pop-to-ebp
19675     c3/return
19676 
19677 dump-var:  # indent: int, v: (addr handle var)
19678     # . prologue
19679     55/push-ebp
19680     89/<- %ebp 4/r32/esp
19681     # . save registers
19682     50/push-eax
19683     53/push-ebx
19684     # eax = v
19685     8b/-> *(ebp+0xc) 0/r32/eax
19686     #
19687     (write-int32-hex-buffered Stderr *eax)
19688     (write-buffered Stderr ",")
19689     (write-int32-hex-buffered Stderr *(eax+4))
19690     (write-buffered Stderr "->")
19691     (lookup *eax *(eax+4))
19692     (write-int32-hex-buffered Stderr %eax)
19693     (write-buffered Stderr Newline)
19694     (flush Stderr)
19695     {
19696       3d/compare-eax-and 0/imm32
19697       0f 84/jump-if-= break/disp32
19698       (emit-indent Stderr *(ebp+8))
19699       (write-buffered Stderr "name: ")
19700       89/<- %ebx 0/r32/eax
19701       (write-int32-hex-buffered Stderr *ebx)  # Var-name
19702       (write-buffered Stderr ",")
19703       (write-int32-hex-buffered Stderr *(ebx+4))  # Var-name
19704       (write-buffered Stderr "->")
19705       (lookup *ebx *(ebx+4))  # Var-name
19706       (write-int32-hex-buffered Stderr %eax)
19707       {
19708         3d/compare-eax-and 0/imm32
19709         74/jump-if-= break/disp8
19710         (write-buffered Stderr Space)
19711         (write-buffered Stderr %eax)
19712       }
19713       (write-buffered Stderr Newline)
19714       (flush Stderr)
19715       (emit-indent Stderr *(ebp+8))
19716       (write-buffered Stderr "block depth: ")
19717       (write-int32-hex-buffered Stderr *(ebx+0x10))  # Var-block-depth
19718       (write-buffered Stderr Newline)
19719       (flush Stderr)
19720       (emit-indent Stderr *(ebp+8))
19721       (write-buffered Stderr "stack offset: ")
19722       (write-int32-hex-buffered Stderr *(ebx+0x14))  # Var-offset
19723       (write-buffered Stderr Newline)
19724       (flush Stderr)
19725       (emit-indent Stderr *(ebp+8))
19726       (write-buffered Stderr "reg: ")
19727       (write-int32-hex-buffered Stderr *(ebx+0x18))  # Var-register
19728       (write-buffered Stderr ",")
19729       (write-int32-hex-buffered Stderr *(ebx+0x1c))  # Var-register
19730       (write-buffered Stderr "->")
19731       (flush Stderr)
19732       (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register
19733       (write-int32-hex-buffered Stderr %eax)
19734       {
19735         3d/compare-eax-and 0/imm32
19736         74/jump-if-= break/disp8
19737         (write-buffered Stderr Space)
19738         (write-buffered Stderr %eax)
19739       }
19740       (write-buffered Stderr Newline)
19741       (flush Stderr)
19742     }
19743 $dump-var:end:
19744     # . restore registers
19745     5b/pop-to-ebx
19746     58/pop-to-eax
19747     # . epilogue
19748     89/<- %esp 5/r32/ebp
19749     5d/pop-to-ebp
19750     c3/return
19751 
19752 #######################################################
19753 # Type-checking
19754 #######################################################
19755 
19756 check-mu-types:  # err: (addr buffered-file), ed: (addr exit-descriptor)
19757     # . prologue
19758     55/push-ebp
19759     89/<- %ebp 4/r32/esp
19760     # . save registers
19761     50/push-eax
19762     # var curr/eax: (addr function) = lookup(Program->functions)
19763     (lookup *_Program-functions *_Program-functions->payload)  # => eax
19764     {
19765 $check-mu-types:loop:
19766       # if (curr == null) break
19767       3d/compare-eax-and 0/imm32
19768       0f 84/jump-if-= break/disp32
19769 +--  8 lines: #?       # dump curr->name ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
19777       (check-mu-function %eax *(ebp+8) *(ebp+0xc))
19778       # curr = lookup(curr->next)
19779       (lookup *(eax+0x20) *(eax+0x24))  # Function-next Function-next => eax
19780       e9/jump loop/disp32
19781     }
19782 $check-mu-types:end:
19783     # . restore registers
19784     58/pop-to-eax
19785     # . epilogue
19786     89/<- %esp 5/r32/ebp
19787     5d/pop-to-ebp
19788     c3/return
19789 
19790 check-mu-function:  # fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
19791     # . prologue
19792     55/push-ebp
19793     89/<- %ebp 4/r32/esp
19794     # . save registers
19795     50/push-eax
19796     56/push-esi
19797     # esi = f
19798     8b/-> *(ebp+8) 6/r32/esi
19799     # outputs
19800     (lookup *(esi+0x10) *(esi+0x14))  # Function-outputs Function-outputs => eax
19801     (check-all-unique-registers %eax %esi *(ebp+0xc) *(ebp+0x10))
19802     # body
19803     (lookup *(esi+0x18) *(esi+0x1c))  # Function-body Function-body => eax
19804     (check-mu-block %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10))
19805     # if function has no outputs, we're done
19806     81 7/subop/compare *(esi+0x10) 0/imm32
19807     74/jump-if-= $check-mu-function:end/disp8
19808     # some final checks on body
19809     (check-final-stmt-is-return %eax %esi *(ebp+0xc) *(ebp+0x10))
19810     (check-no-breaks %eax %esi *(ebp+0xc) *(ebp+0x10))
19811 $check-mu-function:end:
19812     # . restore registers
19813     5e/pop-to-esi
19814     58/pop-to-eax
19815     # . epilogue
19816     89/<- %esp 5/r32/ebp
19817     5d/pop-to-ebp
19818     c3/return
19819 
19820 check-mu-block:  # block: (addr block), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
19821     # . prologue
19822     55/push-ebp
19823     89/<- %ebp 4/r32/esp
19824     # . save registers
19825     50/push-eax
19826     # eax = block
19827     8b/-> *(ebp+8) 0/r32/eax
19828     # var stmts/eax: (addr list stmt) = lookup(block->statements)
19829     (lookup *(eax+4) *(eax+8))  # Block-stmts Block-stmts => eax
19830     #
19831     {
19832 $check-mu-block:check-empty:
19833       3d/compare-eax-and 0/imm32
19834       0f 84/jump-if-= break/disp32
19835       # emit block->statements
19836       (check-mu-stmt-list %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
19837     }
19838 $check-mu-block:end:
19839     # . restore registers
19840     58/pop-to-eax
19841     # . epilogue
19842     89/<- %esp 5/r32/ebp
19843     5d/pop-to-ebp
19844     c3/return
19845 
19846 check-mu-stmt-list:  # stmts: (addr list stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
19847     # . prologue
19848     55/push-ebp
19849     89/<- %ebp 4/r32/esp
19850     # . save registers
19851     50/push-eax
19852     56/push-esi
19853     # esi = stmts
19854     8b/-> *(ebp+8) 6/r32/esi
19855     {
19856 $check-mu-stmt-list:loop:
19857       81 7/subop/compare %esi 0/imm32
19858       0f 84/jump-if-= break/disp32
19859       # var curr-stmt/eax: (addr stmt) = lookup(stmts->value)
19860       (lookup *esi *(esi+4))  # List-value List-value => eax
19861       {
19862 $check-mu-stmt-list:check-for-block:
19863         81 7/subop/compare *eax 0/imm32/block  # Stmt-tag
19864         75/jump-if-!= break/disp8
19865 $check-mu-stmt-list:block:
19866         (check-mu-block %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
19867         eb/jump $check-mu-stmt-list:continue/disp8
19868       }
19869       {
19870 $check-mu-stmt-list:check-for-stmt1:
19871         81 7/subop/compare *eax 1/imm32/stmt1  # Stmt-tag
19872         0f 85/jump-if-!= break/disp32
19873 $check-mu-stmt-list:stmt1:
19874         (check-mu-stmt %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
19875         eb/jump $check-mu-stmt-list:continue/disp8
19876       }
19877       {
19878 $check-mu-stmt-list:check-for-reg-var-def:
19879         81 7/subop/compare *eax 3/imm32/reg-var-def  # Stmt-tag
19880         0f 85/jump-if-!= break/disp32
19881 $check-mu-stmt-list:reg-var-def:
19882         (check-mu-stmt %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
19883         eb/jump $check-mu-stmt-list:continue/disp8
19884       }
19885 $check-mu-stmt-list:continue:
19886       # TODO: raise an error on unrecognized Stmt-tag
19887       (lookup *(esi+8) *(esi+0xc))  # List-next List-next => eax
19888       89/<- %esi 0/r32/eax
19889       e9/jump loop/disp32
19890     }
19891 $check-mu-stmt-list:end:
19892     # . restore registers
19893     5e/pop-to-esi
19894     58/pop-to-eax
19895     # . epilogue
19896     89/<- %esp 5/r32/ebp
19897     5d/pop-to-ebp
19898     c3/return
19899 
19900 check-mu-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
19901     # . prologue
19902     55/push-ebp
19903     89/<- %ebp 4/r32/esp
19904     # . save registers
19905     50/push-eax
19906     # - if stmt's operation matches a primitive, check against it
19907     (has-primitive-name? *(ebp+8))  # => eax
19908     3d/compare-eax-and 0/imm32/false
19909     {
19910       74/jump-if-= break/disp8
19911       (check-mu-primitive *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
19912       e9/jump $check-mu-stmt:end/disp32
19913     }
19914     # - otherwise find a function to check against
19915     # var f/eax: (addr function) = lookup(*Program->functions)
19916     (lookup *_Program-functions *_Program-functions->payload)  # => eax
19917     (find-matching-function %eax *(ebp+8))  # => eax
19918     3d/compare-eax-and 0/imm32
19919     {
19920       74/jump-if-= break/disp8
19921       (check-mu-call *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
19922       eb/jump $check-mu-stmt:end/disp8
19923     }
19924     # var f/eax: (addr function) = lookup(*Program->signatures)
19925     (lookup *_Program-signatures *_Program-signatures->payload)  # => eax
19926     (find-matching-function %eax *(ebp+8))  # => eax
19927     3d/compare-eax-and 0/imm32
19928     {
19929       74/jump-if-= break/disp8
19930       (check-mu-call *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
19931       eb/jump $check-mu-stmt:end/disp8
19932     }
19933     # - otherwise abort
19934     e9/jump $check-mu-stmt:unknown-call/disp32
19935 $check-mu-stmt:end:
19936     # . restore registers
19937     58/pop-to-eax
19938     # . epilogue
19939     89/<- %esp 5/r32/ebp
19940     5d/pop-to-ebp
19941     c3/return
19942 
19943 $check-mu-stmt:unknown-call:
19944     (write-buffered *(ebp+0x10) "unknown function '")
19945     8b/-> *(ebp+8) 0/r32/eax
19946     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
19947     (write-buffered *(ebp+0x10) %eax)
19948     (write-buffered *(ebp+0x10) "'\n")
19949     (flush *(ebp+0x10))
19950     (stop *(ebp+0x14) 1)
19951     # never gets here
19952 
19953 has-primitive-name?:  # stmt: (addr stmt) -> result/eax: boolean
19954     # . prologue
19955     55/push-ebp
19956     89/<- %ebp 4/r32/esp
19957     # . save registers
19958     51/push-ecx
19959     56/push-esi
19960     # var name/esi: (addr array byte) = lookup(stmt->operation)
19961     8b/-> *(ebp+8) 6/r32/esi
19962     (lookup *(esi+4) *(esi+8))  # Stmt1-operation Stmt1-operation => eax
19963     89/<- %esi 0/r32/eax
19964     # if (name == "return") return true
19965     (string-equal? %esi "return")  # => eax
19966     3d/compare-eax-and 0/imm32/false
19967     0f 85/jump-if-!= $has-primitive-name?:end/disp32
19968     # if (name == "get") return true
19969     (string-equal? %esi "get")  # => eax
19970     3d/compare-eax-and 0/imm32/false
19971     0f 85/jump-if-!= $has-primitive-name?:end/disp32
19972     # if (name == "index") return true
19973     (string-equal? %esi "index")  # => eax
19974     3d/compare-eax-and 0/imm32/false
19975     0f 85/jump-if-!= $has-primitive-name?:end/disp32
19976     # if (name == "length") return true
19977     (string-equal? %esi "length")  # => eax
19978     3d/compare-eax-and 0/imm32/false
19979     0f 85/jump-if-!= $has-primitive-name?:end/disp32
19980     # if (name == "compute-offset") return true
19981     (string-equal? %esi "compute-offset")  # => eax
19982     3d/compare-eax-and 0/imm32/false
19983     0f 85/jump-if-!= $has-primitive-name?:end/disp32
19984     # if (name == "copy-object") return true
19985     (string-equal? %esi "copy-object")  # => eax
19986     3d/compare-eax-and 0/imm32/false
19987     0f 85/jump-if-!= $has-primitive-name?:end/disp32
19988     # if (name == "clear-object") return true
19989     (string-equal? %esi "clear-object")  # => eax
19990     3d/compare-eax-and 0/imm32/false
19991     0f 85/jump-if-!= $has-primitive-name?:end/disp32
19992     # if (name == "allocate") return true
19993     (string-equal? %esi "allocate")  # => eax
19994     3d/compare-eax-and 0/imm32/false
19995     0f 85/jump-if-!= $has-primitive-name?:end/disp32
19996     # if (name == "populate") return true
19997     (string-equal? %esi "populate")  # => eax
19998     3d/compare-eax-and 0/imm32/false
19999     0f 85/jump-if-!= $has-primitive-name?:end/disp32
20000     # if (name == "populate-stream") return true
20001     (string-equal? %esi "populate-stream")  # => eax
20002     3d/compare-eax-and 0/imm32/false
20003     0f 85/jump-if-!= $has-primitive-name?:end/disp32
20004     # if (name == "read-from-stream") return true
20005     (string-equal? %esi "read-from-stream")  # => eax
20006     3d/compare-eax-and 0/imm32/false
20007     0f 85/jump-if-!= $has-primitive-name?:end/disp32
20008     # if (name == "write-to-stream") return true
20009     (string-equal? %esi "write-to-stream")  # => eax
20010     3d/compare-eax-and 0/imm32/false
20011     0f 85/jump-if-!= $has-primitive-name?:end/disp32
20012     # var curr/ecx: (addr primitive) = Primitives
20013     b9/copy-to-ecx Primitives/imm32
20014     {
20015 $has-primitive-name?:loop:
20016       # if (curr == null) break
20017       81 7/subop/compare %ecx 0/imm32
20018       74/jump-if-= break/disp8
20019       # if (primitive->name == name) return true
20020       (lookup *ecx *(ecx+4))  # Primitive-name Primitive-name => eax
20021 #?       (write-buffered Stderr %eax)
20022 #?       (write-buffered Stderr Newline)
20023 #?       (flush Stderr)
20024       (string-equal? %esi %eax)  # => eax
20025       3d/compare-eax-and 0/imm32/false
20026       75/jump-if-!= $has-primitive-name?:end/disp8
20027 $has-primitive-name?:next-primitive:
20028       # curr = curr->next
20029       (lookup *(ecx+0x3c) *(ecx+0x40))  # Primitive-next Primitive-next => eax
20030       89/<- %ecx 0/r32/eax
20031       #
20032       e9/jump loop/disp32
20033     }
20034     # return null
20035     b8/copy-to-eax 0/imm32
20036 $has-primitive-name?:end:
20037     # . restore registers
20038     5e/pop-to-esi
20039     59/pop-to-ecx
20040     # . epilogue
20041     89/<- %esp 5/r32/ebp
20042     5d/pop-to-ebp
20043     c3/return
20044 
20045 check-mu-primitive:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
20046     # . prologue
20047     55/push-ebp
20048     89/<- %ebp 4/r32/esp
20049     # . save registers
20050     50/push-eax
20051     51/push-ecx
20052     # var op/ecx: (addr array byte) = lookup(stmt->operation)
20053     8b/-> *(ebp+8) 0/r32/eax
20054     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
20055     89/<- %ecx 0/r32/eax
20056     # if (op == "copy") check-mu-copy-stmt
20057     {
20058       (string-equal? %ecx "copy")  # => eax
20059       3d/compare-eax-and 0/imm32/false
20060       74/jump-if-= break/disp8
20061       (check-mu-copy-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20062       e9/jump $check-mu-primitive:end/disp32
20063     }
20064     # if (op == "copy-to") check-mu-copy-to-stmt
20065     {
20066       (string-equal? %ecx "copy-to")  # => eax
20067       3d/compare-eax-and 0/imm32/false
20068       74/jump-if-= break/disp8
20069       (check-mu-copy-to-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20070       e9/jump $check-mu-primitive:end/disp32
20071     }
20072     # if (op == "compare") check-mu-compare-stmt
20073     {
20074       (string-equal? %ecx "compare")  # => eax
20075       3d/compare-eax-and 0/imm32/false
20076       74/jump-if-= break/disp8
20077       (check-mu-compare-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20078       e9/jump $check-mu-primitive:end/disp32
20079     }
20080     # if (op == "address") check-mu-address-stmt
20081     {
20082       (string-equal? %ecx "address")  # => eax
20083       3d/compare-eax-and 0/imm32/false
20084       74/jump-if-= break/disp8
20085       (check-mu-address-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20086       e9/jump $check-mu-primitive:end/disp32
20087     }
20088     # if (op == "return") check-mu-return-stmt
20089     {
20090       (string-equal? %ecx "return")  # => eax
20091       3d/compare-eax-and 0/imm32/false
20092       74/jump-if-= break/disp8
20093       (check-mu-return-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20094       e9/jump $check-mu-primitive:end/disp32
20095     }
20096     # if (op == "get") check-mu-get-stmt
20097     {
20098       (string-equal? %ecx "get")  # => eax
20099       3d/compare-eax-and 0/imm32/false
20100       74/jump-if-= break/disp8
20101       (check-mu-get-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20102       e9/jump $check-mu-primitive:end/disp32
20103     }
20104     # if (op == "index") check-mu-index-stmt
20105     {
20106       (string-equal? %ecx "index")  # => eax
20107       3d/compare-eax-and 0/imm32/false
20108       74/jump-if-= break/disp8
20109       (check-mu-index-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20110       e9/jump $check-mu-primitive:end/disp32
20111     }
20112     # if (op == "length") check-mu-length-stmt
20113     {
20114       (string-equal? %ecx "length")  # => eax
20115       3d/compare-eax-and 0/imm32/false
20116       74/jump-if-= break/disp8
20117       (check-mu-length-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20118       e9/jump $check-mu-primitive:end/disp32
20119     }
20120     # if (op == "compute-offset") check-mu-compute-offset-stmt
20121     {
20122       (string-equal? %ecx "compute-offset")  # => eax
20123       3d/compare-eax-and 0/imm32/false
20124       74/jump-if-= break/disp8
20125       (check-mu-compute-offset-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20126       e9/jump $check-mu-primitive:end/disp32
20127     }
20128     # if (op == "copy-object") check-mu-copy-object-stmt
20129     {
20130       (string-equal? %ecx "copy-object")  # => eax
20131       3d/compare-eax-and 0/imm32/false
20132       74/jump-if-= break/disp8
20133       (check-mu-copy-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20134       e9/jump $check-mu-primitive:end/disp32
20135     }
20136     # if (op == "clear-object") check-mu-clear-object-stmt
20137     {
20138       (string-equal? %ecx "clear-object")  # => eax
20139       3d/compare-eax-and 0/imm32/false
20140       74/jump-if-= break/disp8
20141       (check-mu-clear-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20142       e9/jump $check-mu-primitive:end/disp32
20143     }
20144     # if (op == "allocate") check-mu-allocate-stmt
20145     {
20146       (string-equal? %ecx "allocate")  # => eax
20147       3d/compare-eax-and 0/imm32/false
20148       74/jump-if-= break/disp8
20149       (check-mu-allocate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20150       e9/jump $check-mu-primitive:end/disp32
20151     }
20152     # if (op == "populate") check-mu-populate-stmt
20153     {
20154       (string-equal? %ecx "populate")  # => eax
20155       3d/compare-eax-and 0/imm32/false
20156       74/jump-if-= break/disp8
20157       (check-mu-populate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20158       e9/jump $check-mu-primitive:end/disp32
20159     }
20160     # if (op == "populate-stream") check-mu-populate-stream-stmt
20161     {
20162       (string-equal? %ecx "populate-stream")  # => eax
20163       3d/compare-eax-and 0/imm32/false
20164       74/jump-if-= break/disp8
20165       (check-mu-populate-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20166       e9/jump $check-mu-primitive:end/disp32
20167     }
20168     # if (op == "read-from-stream") check-mu-read-from-stream-stmt
20169     {
20170       (string-equal? %ecx "read-from-stream")  # => eax
20171       3d/compare-eax-and 0/imm32/false
20172       74/jump-if-= break/disp8
20173       (check-mu-read-from-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20174       e9/jump $check-mu-primitive:end/disp32
20175     }
20176     # if (op == "write-to-stream") check-mu-write-to-stream-stmt
20177     {
20178       (string-equal? %ecx "write-to-stream")  # => eax
20179       3d/compare-eax-and 0/imm32/false
20180       74/jump-if-= break/disp8
20181       (check-mu-write-to-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20182       e9/jump $check-mu-primitive:end/disp32
20183     }
20184     # if (op == "convert") check-mu-convert-stmt
20185     {
20186       (string-equal? %ecx "convert")  # => eax
20187       3d/compare-eax-and 0/imm32/false
20188       74/jump-if-= break/disp8
20189       (check-mu-convert-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20190       e9/jump $check-mu-primitive:end/disp32
20191     }
20192     # otherwise check-numberlike-stmt
20193     (check-mu-numberlike-primitive *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20194 $check-mu-primitive:end:
20195     # . restore registers
20196     59/pop-to-ecx
20197     58/pop-to-eax
20198     # . epilogue
20199     89/<- %esp 5/r32/ebp
20200     5d/pop-to-ebp
20201     c3/return
20202 
20203 # by default, Mu primitives should only operate on 'number-like' types
20204 check-mu-numberlike-primitive:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
20205     # . prologue
20206     55/push-ebp
20207     89/<- %ebp 4/r32/esp
20208     # . save registers
20209     50/push-eax
20210     51/push-ecx
20211     56/push-esi
20212     # esi = stmt
20213     8b/-> *(ebp+8) 6/r32/esi
20214     # var gas/ecx: int = 2
20215     b9/copy-to-ecx 2/imm32
20216     # - check at most 1 output
20217     # var output/eax: (addr stmt-var) = stmt->outputs
20218     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
20219     {
20220       3d/compare-eax-and 0/imm32
20221       74/jump-if-= break/disp8
20222 $check-mu-numberlike-primitive:output:
20223       (check-mu-numberlike-output %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20224       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
20225       3d/compare-eax-and 0/imm32
20226       0f 85/jump-if-!= $check-mu-numberlike-primitive:error-too-many-outputs/disp32
20227       # check output is in a register
20228       # --gas
20229       49/decrement-ecx
20230     }
20231     # - check first inout
20232     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
20233     {
20234       3d/compare-eax-and 0/imm32
20235       0f 84/jump-if-= $check-mu-numberlike-primitive:end/disp32
20236 $check-mu-numberlike-primitive:first-inout:
20237       (check-mu-numberlike-arg %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20238       # --gas
20239       49/decrement-ecx
20240     }
20241     # - check second inout
20242     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
20243     {
20244       3d/compare-eax-and 0/imm32
20245       74/jump-if-= $check-mu-numberlike-primitive:end/disp8
20246 $check-mu-numberlike-primitive:second-inout:
20247       # is a second inout allowed?
20248       81 7/subop/compare %ecx 0/imm32
20249       0f 84/jump-if-= $check-mu-numberlike-primitive:error-too-many-inouts/disp32
20250 $check-mu-numberlike-primitive:second-inout-permitted:
20251       (check-mu-numberlike-arg %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20252     }
20253 $check-mu-numberlike-primitive:third-inout:
20254     # if there's a third arg, raise an error
20255     81 7/subop/compare *(eax+8) 0/imm32  # Stmt-var-next
20256     0f 85/jump-if-!= $check-mu-numberlike-primitive:error-too-many-inouts/disp32
20257 $check-mu-numberlike-primitive:end:
20258     # . restore registers
20259     5e/pop-to-esi
20260     59/pop-to-ecx
20261     58/pop-to-eax
20262     # . epilogue
20263     89/<- %esp 5/r32/ebp
20264     5d/pop-to-ebp
20265     c3/return
20266 
20267 $check-mu-numberlike-primitive:error-too-many-inouts:
20268     (write-buffered *(ebp+0x10) "fn ")
20269     8b/-> *(ebp+0xc) 0/r32/eax
20270     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20271     (write-buffered *(ebp+0x10) %eax)
20272     (write-buffered *(ebp+0x10) ": stmt ")
20273     (lookup *(esi+4) *(esi+8))  # Stmt1-operation Stmt1-operation => eax
20274     (write-buffered *(ebp+0x10) %eax)
20275     (write-buffered *(ebp+0x10) ": too many inouts; most primitives support at most two arguments, across inouts and outputs\n")
20276     (flush *(ebp+0x10))
20277     (stop *(ebp+0x14) 1)
20278     # never gets here
20279 
20280 $check-mu-numberlike-primitive:error-too-many-outputs:
20281     (write-buffered *(ebp+0x10) "fn ")
20282     8b/-> *(ebp+0xc) 0/r32/eax
20283     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20284     (write-buffered *(ebp+0x10) %eax)
20285     (write-buffered *(ebp+0x10) ": stmt ")
20286     (lookup *(esi+4) *(esi+8))  # Stmt1-operation Stmt1-operation => eax
20287     (write-buffered *(ebp+0x10) %eax)
20288     (write-buffered *(ebp+0x10) ": too many outputs; most primitives support at most one output\n")
20289     (flush *(ebp+0x10))
20290     (stop *(ebp+0x14) 1)
20291     # never gets here
20292 
20293 check-mu-numberlike-arg:  # v: (addr stmt-var), stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
20294     # . prologue
20295     55/push-ebp
20296     89/<- %ebp 4/r32/esp
20297     # . save registers
20298     50/push-eax
20299     56/push-esi
20300     # var t/esi: (addr type-tree) = lookup(v->value->type)
20301     8b/-> *(ebp+8) 0/r32/eax
20302     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
20303     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20304     89/<- %esi 0/r32/eax
20305 $check-mu-numberlike-arg:check-literal:
20306     # if t is an int, return
20307     (is-simple-mu-type? %esi 0)  # literal => eax
20308     3d/compare-eax-and 0/imm32/false
20309     0f 85/jump-if-!= $check-mu-numberlike-arg:end/disp32
20310 $check-mu-numberlike-arg:check-addr:
20311     # if t is an addr and v is dereferenced, return whether t->payload is an addr
20312     {
20313       (is-mu-addr-type? %esi)  # => eax
20314       3d/compare-eax-and 0/imm32/false
20315       74/jump-if-= break/disp8
20316       8b/-> *(ebp+8) 0/r32/eax
20317       8b/-> *(eax+0x10) 0/r32/eax  # Stmt-var-is-deref
20318       3d/compare-eax-and 0/imm32/false
20319       {
20320         74/jump-if-= break/disp8
20321         (lookup *(esi+0xc) *(esi+0x10))  # Type-tree-right Type-tree-right => eax
20322         # if t->right is null, t = t->left
20323         81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
20324         {
20325           75/jump-if-!= break/disp8
20326           (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
20327         }
20328         (is-mu-addr-type? %eax)  # => eax
20329         3d/compare-eax-and 0/imm32/false
20330         74/jump-if-= $check-mu-numberlike-arg:end/disp8
20331       }
20332     }
20333 $check-mu-numberlike-arg:output-checks:
20334     (check-mu-numberlike-output *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18))
20335 $check-mu-numberlike-arg:end:
20336     # . restore registers
20337     5e/pop-to-esi
20338     58/pop-to-eax
20339     # . epilogue
20340     89/<- %esp 5/r32/ebp
20341     5d/pop-to-ebp
20342     c3/return
20343 
20344 check-mu-numberlike-output:  # v: (addr stmt-var), stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
20345     # . prologue
20346     55/push-ebp
20347     89/<- %ebp 4/r32/esp
20348     # . save registers
20349     50/push-eax
20350     #
20351     (is-mu-numberlike-output-var? *(ebp+8))  # => eax
20352     3d/compare-eax-and 0/imm32/false
20353     0f 84/jump-if-= $check-mu-numberlike-output:fail/disp32
20354 $check-mu-numberlike-output:end:
20355     # . restore registers
20356     58/pop-to-eax
20357     # . epilogue
20358     89/<- %esp 5/r32/ebp
20359     5d/pop-to-ebp
20360     c3/return
20361 
20362 $check-mu-numberlike-output:fail:
20363     # otherwise raise an error
20364     (write-buffered *(ebp+0x14) "fn ")
20365     8b/-> *(ebp+0x10) 0/r32/eax
20366     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20367     (write-buffered *(ebp+0x14) %eax)
20368     (write-buffered *(ebp+0x14) ": stmt ")
20369     8b/-> *(ebp+0xc) 0/r32/eax
20370     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
20371     (write-buffered *(ebp+0x14) %eax)
20372     (write-buffered *(ebp+0x14) ": '")
20373     8b/-> *(ebp+8) 0/r32/eax
20374     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
20375     (lookup *eax *(eax+4))  # Var-name Var-name => eax
20376     (write-buffered *(ebp+0x14) %eax)
20377     (write-buffered *(ebp+0x14) "' must be a non-addr non-offset scalar\n")
20378     (flush *(ebp+0x14))
20379     (stop *(ebp+0x18) 1)
20380     # never gets here
20381 
20382 is-mu-numberlike-output-var?:  # v: (addr stmt-var) -> result/eax: boolean
20383     # . prologue
20384     55/push-ebp
20385     89/<- %ebp 4/r32/esp
20386     #
20387     8b/-> *(ebp+8) 0/r32/eax
20388     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
20389     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20390     (is-mu-numberlike-output? %eax)  # => eax
20391 $is-mu-numberlike-output-var?:end:
20392     # . epilogue
20393     89/<- %esp 5/r32/ebp
20394     5d/pop-to-ebp
20395     c3/return
20396 
20397 is-mu-numberlike-output?:  # v: (addr type-tree) -> result/eax: boolean
20398     # . prologue
20399     55/push-ebp
20400     89/<- %ebp 4/r32/esp
20401     # . save registers
20402     56/push-esi
20403     # var t/esi: (addr type-tree) = lookup(v->value->type)
20404     8b/-> *(ebp+8) 6/r32/esi
20405 $is-mu-numberlike-output?:check-int:
20406     # if t is an int, return
20407     (is-simple-mu-type? %esi 1)  # int => eax
20408     3d/compare-eax-and 0/imm32/false
20409     0f 85/jump-if-!= $is-mu-numberlike-output?:return-true/disp32
20410 $is-mu-numberlike-output?:check-float:
20411     # if t is a float, return
20412     (is-simple-mu-type? %esi 0xf)  # float => eax
20413     3d/compare-eax-and 0/imm32/false
20414     75/jump-if-!= $is-mu-numberlike-output?:return-true/disp8
20415 $is-mu-numberlike-output?:check-boolean:
20416     # if t is a boolean, return
20417     (is-simple-mu-type? %esi 5)  # boolean => eax
20418     3d/compare-eax-and 0/imm32/false
20419     75/jump-if-!= $is-mu-numberlike-output?:return-true/disp8
20420 $is-mu-numberlike-output?:check-byte:
20421     # if t is a byte, return
20422     (is-simple-mu-type? %esi 8)  # byte => eax
20423     3d/compare-eax-and 0/imm32/false
20424     75/jump-if-!= $is-mu-numberlike-output?:return-true/disp8
20425 $is-mu-numberlike-output?:check-code-point:
20426     # if t is a code-point, return
20427     (is-simple-mu-type? %esi 0xd)  # code-point => eax
20428     3d/compare-eax-and 0/imm32/false
20429     75/jump-if-!= $is-mu-numberlike-output?:return-true/disp8
20430 $is-mu-numberlike-output?:check-grapheme:
20431     # if t is a grapheme, return
20432     (is-simple-mu-type? %esi 0xe)  # grapheme => eax
20433     3d/compare-eax-and 0/imm32/false
20434     75/jump-if-!= $is-mu-numberlike-output?:return-true/disp8
20435 $is-mu-numberlike-output?:return-false:
20436     b8/copy-to-eax 0/imm32/false
20437     eb/jump $is-mu-numberlike-output?:end/disp8
20438 $is-mu-numberlike-output?:return-true:
20439     b8/copy-to-eax 1/imm32/true
20440 $is-mu-numberlike-output?:end:
20441     # . restore registers
20442     5e/pop-to-esi
20443     # . epilogue
20444     89/<- %esp 5/r32/ebp
20445     5d/pop-to-ebp
20446     c3/return
20447 
20448 check-mu-copy-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
20449     # . prologue
20450     55/push-ebp
20451     89/<- %ebp 4/r32/esp
20452     # . save registers
20453     50/push-eax
20454     51/push-ecx
20455     52/push-edx
20456     56/push-esi
20457     57/push-edi
20458     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
20459     81 5/subop/subtract %esp 0x60/imm32
20460     68/push 0x60/imm32/size
20461     68/push 0/imm32/read
20462     68/push 0/imm32/write
20463     89/<- %edx 4/r32/esp
20464 $check-mu-copy-stmt:get-output:
20465     # esi = stmt
20466     8b/-> *(ebp+8) 6/r32/esi
20467     # var output/edi: (addr stmt-var) = stmt->outputs
20468     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
20469     89/<- %edi 0/r32/eax
20470     # zero outputs
20471     3d/compare-eax-and 0/imm32
20472     0f 84/jump-if-= $check-mu-copy-stmt:error-no-output/disp32
20473     # > 1 output
20474     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
20475     3d/compare-eax-and 0/imm32
20476     0f 85/jump-if-!= $check-mu-copy-stmt:error-too-many-outputs/disp32
20477 $check-mu-copy-stmt:get-inout:
20478     # var inout/esi: (addr stmt-var) = stmt->inouts
20479     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
20480     89/<- %esi 0/r32/eax
20481     # zero inouts
20482     3d/compare-eax-and 0/imm32
20483     0f 84/jump-if-= $check-mu-copy-stmt:error-no-inout/disp32
20484     # > 1 inout
20485     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
20486     3d/compare-eax-and 0/imm32
20487     0f 85/jump-if-!= $check-mu-copy-stmt:error-too-many-inouts/disp32
20488 $check-mu-copy-stmt:types:
20489     # var inout-type/ecx: (addr type-tree) = inout->value->type
20490     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
20491     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20492     89/<- %ecx 0/r32/eax
20493     # if (inout->is-deref?) inout-type = inout-type->payload
20494     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
20495     3d/compare-eax-and 0/imm32/false
20496     {
20497       74/jump-if-= break/disp8
20498       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
20499       # if inout-type->right is null, t = inout-type->left
20500       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
20501       {
20502         75/jump-if-!= break/disp8
20503         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
20504       }
20505       89/<- %ecx 0/r32/eax
20506     }
20507     # if output not in register, abort
20508     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
20509     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
20510     3d/compare-eax-and 0/imm32
20511     0f 84/jump-if-= $check-mu-copy-stmt:error-output-not-in-register/disp32
20512     # if inout is not a scalar, abort
20513     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
20514     (size-of %eax)  # => eax
20515     3d/compare-eax-and 4/imm32
20516     0f 8f/jump-if-> $check-mu-copy-stmt:error-inout-too-large/disp32
20517     # var output-type/eax: (addr type-tree) = output->value->type
20518     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
20519     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20520     # if (inout-type == output-type) return
20521     (type-match? %eax %ecx %edx)  # => eax
20522     3d/compare-eax-and 0/imm32
20523     0f 85/jump-if-!= $check-mu-copy-stmt:end/disp32
20524     # if output is an addr and inout is 0, return
20525     {
20526       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
20527       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20528       (is-mu-addr-type? %eax)  # => eax
20529       3d/compare-eax-and 0/imm32/false
20530       74/jump-if-= break/disp8
20531       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
20532       (lookup *eax *(eax+4))  # Var-name Var-name => eax
20533       (string-equal? %eax "0")  # => eax
20534       3d/compare-eax-and 0/imm32/false
20535       74/jump-if-= break/disp8
20536       e9/jump $check-mu-copy-stmt:end/disp32
20537     }
20538     # if output is an offset and inout is 0, return
20539     {
20540       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
20541       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20542       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
20543       75/jump-if-!= break/disp8
20544       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
20545       (is-simple-mu-type? %eax 7)  # offset => eax
20546       3d/compare-eax-and 0/imm32/false
20547       74/jump-if-= break/disp8
20548       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
20549       (lookup *eax *(eax+4))  # Var-name Var-name => eax
20550       (string-equal? %eax "0")  # => eax
20551       3d/compare-eax-and 0/imm32/false
20552       74/jump-if-= break/disp8
20553       eb/jump $check-mu-copy-stmt:end/disp8
20554     }
20555     # if output is not number-like, abort
20556     (check-mu-numberlike-output %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20557 $check-mu-copy-stmt:end:
20558     # . reclaim locals
20559     81 0/subop/add %esp 0x6c/imm32
20560     # . restore registers
20561     5f/pop-to-edi
20562     5e/pop-to-esi
20563     5a/pop-to-edx
20564     59/pop-to-ecx
20565     58/pop-to-eax
20566     # . epilogue
20567     89/<- %esp 5/r32/ebp
20568     5d/pop-to-ebp
20569     c3/return
20570 
20571 $check-mu-copy-stmt:error-no-inout:
20572     (write-buffered *(ebp+0x10) "fn ")
20573     8b/-> *(ebp+0xc) 0/r32/eax
20574     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20575     (write-buffered *(ebp+0x10) %eax)
20576     (write-buffered *(ebp+0x10) ": stmt 'copy' expects an inout\n")
20577     (flush *(ebp+0x10))
20578     (stop *(ebp+0x14) 1)
20579     # never gets here
20580 
20581 $check-mu-copy-stmt:error-too-many-inouts:
20582     (write-buffered *(ebp+0x10) "fn ")
20583     8b/-> *(ebp+0xc) 0/r32/eax
20584     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20585     (write-buffered *(ebp+0x10) %eax)
20586     (write-buffered *(ebp+0x10) ": stmt 'copy' must have just one inout\n")
20587     (flush *(ebp+0x10))
20588     (stop *(ebp+0x14) 1)
20589     # never gets here
20590 
20591 $check-mu-copy-stmt:error-no-output:
20592     (write-buffered *(ebp+0x10) "fn ")
20593     8b/-> *(ebp+0xc) 0/r32/eax
20594     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20595     (write-buffered *(ebp+0x10) %eax)
20596     (write-buffered *(ebp+0x10) ": stmt 'copy' expects an output\n")
20597     (flush *(ebp+0x10))
20598     (stop *(ebp+0x14) 1)
20599     # never gets here
20600 
20601 $check-mu-copy-stmt:error-output-not-in-register:
20602     (write-buffered *(ebp+0x10) "fn ")
20603     8b/-> *(ebp+0xc) 0/r32/eax
20604     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20605     (write-buffered *(ebp+0x10) %eax)
20606     (write-buffered *(ebp+0x10) ": stmt copy: output '")
20607     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
20608     (lookup *eax *(eax+4))  # Var-name Var-name => eax
20609     (write-buffered *(ebp+0x10) %eax)
20610     (write-buffered *(ebp+0x10) "' not in a register\n")
20611     (flush *(ebp+0x10))
20612     (stop *(ebp+0x14) 1)
20613     # never gets here
20614 
20615 $check-mu-copy-stmt:error-too-many-outputs:
20616     (write-buffered *(ebp+0x10) "fn ")
20617     8b/-> *(ebp+0xc) 0/r32/eax
20618     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20619     (write-buffered *(ebp+0x10) %eax)
20620     (write-buffered *(ebp+0x10) ": stmt 'copy' must have just one output\n")
20621     (flush *(ebp+0x10))
20622     (stop *(ebp+0x14) 1)
20623     # never gets here
20624 
20625 $check-mu-copy-stmt:error-inout-too-large:
20626     (write-buffered *(ebp+0x10) "fn ")
20627     8b/-> *(ebp+0xc) 0/r32/eax
20628     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20629     (write-buffered *(ebp+0x10) %eax)
20630     (write-buffered *(ebp+0x10) ": stmt copy: '")
20631     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
20632     (lookup *eax *(eax+4))  # Var-name Var-name => eax
20633     (write-buffered *(ebp+0x10) %eax)
20634     (write-buffered *(ebp+0x10) "' is too large to fit in a register\n")
20635     (flush *(ebp+0x10))
20636     (stop *(ebp+0x14) 1)
20637     # never gets here
20638 
20639 check-mu-copy-to-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
20640     # . prologue
20641     55/push-ebp
20642     89/<- %ebp 4/r32/esp
20643     # . save registers
20644     50/push-eax
20645     51/push-ecx
20646     52/push-edx
20647     53/push-ebx
20648     56/push-esi
20649     57/push-edi
20650     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
20651     81 5/subop/subtract %esp 0x60/imm32
20652     68/push 0x60/imm32/size
20653     68/push 0/imm32/read
20654     68/push 0/imm32/write
20655     89/<- %edx 4/r32/esp
20656     # esi = stmt
20657     8b/-> *(ebp+8) 6/r32/esi
20658 $check-mu-copy-to-stmt:check-for-output:
20659     # if stmt->outputs abort
20660     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
20661     3d/compare-eax-and 0/imm32
20662     0f 85/jump-if-!= $check-mu-copy-to-stmt:error-too-many-outputs/disp32
20663 $check-mu-copy-to-stmt:get-dest:
20664     # var dest/edi: (addr stmt-var) = stmt->inouts
20665     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
20666     89/<- %edi 0/r32/eax
20667     # zero inouts
20668     3d/compare-eax-and 0/imm32
20669     0f 84/jump-if-= $check-mu-copy-to-stmt:error-incorrect-inouts/disp32
20670 $check-mu-copy-to-stmt:get-src:
20671     # var src/esi: (addr stmt-var) = dest->next
20672     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
20673     89/<- %esi 0/r32/eax
20674     # 1 inout
20675     3d/compare-eax-and 0/imm32
20676     0f 84/jump-if-= $check-mu-copy-to-stmt:error-incorrect-inouts/disp32
20677     # > 2 inouts
20678     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
20679     3d/compare-eax-and 0/imm32
20680     0f 85/jump-if-!= $check-mu-copy-to-stmt:error-incorrect-inouts/disp32
20681 $check-mu-copy-to-stmt:types:
20682     # var src-type/ecx: (addr type-tree) = src->value->type
20683     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
20684     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20685     89/<- %ecx 0/r32/eax
20686     # if src not in register or literal, abort
20687     # (we can't use stack-offset because it hasn't been computed yet)
20688     {
20689       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
20690       (lookup *(eax+0x8) *(eax+0xc))  # Var-type Var-type => eax
20691       (is-simple-mu-type? %eax 0)  # => eax
20692       3d/compare-eax-and 0/imm32
20693       75/jump-if-!= break/disp8
20694       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
20695       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
20696       3d/compare-eax-and 0/imm32
20697       75/jump-if-!= break/disp8
20698       e9/jump $check-mu-copy-to-stmt:error-src-not-literal-or-in-register/disp32
20699     }
20700     # if src is not a scalar, abort
20701     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
20702     (size-of %eax)  # => eax
20703     3d/compare-eax-and 4/imm32
20704     0f 8f/jump-if-> $check-mu-copy-to-stmt:error-src-too-large/disp32
20705     # var dest-type/ebx: (addr type-tree) = dest->value->type
20706     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
20707     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20708     89/<- %ebx 0/r32/eax
20709     # if (dest->is-deref?) dest-type = dest-type->payload
20710     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
20711     3d/compare-eax-and 0/imm32/false
20712     {
20713       74/jump-if-= break/disp8
20714       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
20715       # if dest-type->right is null, dest-type = dest-type->left
20716       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
20717       {
20718         75/jump-if-!= break/disp8
20719         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
20720       }
20721       89/<- %ebx 0/r32/eax
20722     }
20723     # if (src-type == dest-type) return
20724     (type-match? %ebx %ecx %edx)  # => eax
20725     3d/compare-eax-and 0/imm32
20726     0f 85/jump-if-!= $check-mu-copy-to-stmt:end/disp32
20727     # if dest is an addr and src is 0, return
20728     {
20729       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
20730       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20731       (is-mu-addr-type? %eax)  # => eax
20732       3d/compare-eax-and 0/imm32/false
20733       74/jump-if-= break/disp8
20734       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
20735       (lookup *eax *(eax+4))  # Var-name Var-name => eax
20736       (string-equal? %eax "0")  # => eax
20737       3d/compare-eax-and 0/imm32/false
20738       74/jump-if-= break/disp8
20739       eb/jump $check-mu-copy-to-stmt:end/disp8
20740     }
20741     # if dest is not number-like, abort
20742     (check-mu-numberlike-arg %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20743 $check-mu-copy-to-stmt:end:
20744     # . reclaim locals
20745     81 0/subop/add %esp 0x6c/imm32
20746     # . restore registers
20747     5f/pop-to-edi
20748     5e/pop-to-esi
20749     5b/pop-to-ebx
20750     5a/pop-to-edx
20751     59/pop-to-ecx
20752     58/pop-to-eax
20753     # . epilogue
20754     89/<- %esp 5/r32/ebp
20755     5d/pop-to-ebp
20756     c3/return
20757 
20758 $check-mu-copy-to-stmt:error-incorrect-inouts:
20759     (write-buffered *(ebp+0x10) "fn ")
20760     8b/-> *(ebp+0xc) 0/r32/eax
20761     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20762     (write-buffered *(ebp+0x10) %eax)
20763     (write-buffered *(ebp+0x10) ": stmt 'copy-to' must have two inouts\n")
20764     (flush *(ebp+0x10))
20765     (stop *(ebp+0x14) 1)
20766     # never gets here
20767 
20768 $check-mu-copy-to-stmt:error-too-many-outputs:
20769     (write-buffered *(ebp+0x10) "fn ")
20770     8b/-> *(ebp+0xc) 0/r32/eax
20771     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20772     (write-buffered *(ebp+0x10) %eax)
20773     (write-buffered *(ebp+0x10) ": stmt 'copy-to' must not have any outputs\n")
20774     (flush *(ebp+0x10))
20775     (stop *(ebp+0x14) 1)
20776     # never gets here
20777 
20778 $check-mu-copy-to-stmt:error-src-not-literal-or-in-register:
20779     (write-buffered *(ebp+0x10) "fn ")
20780     8b/-> *(ebp+0xc) 0/r32/eax
20781     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20782     (write-buffered *(ebp+0x10) %eax)
20783     (write-buffered *(ebp+0x10) ": stmt copy-to: source (second inout) is in memory\n")
20784     (flush *(ebp+0x10))
20785     (stop *(ebp+0x14) 1)
20786     # never gets here
20787 
20788 $check-mu-copy-to-stmt:error-src-too-large:
20789     (write-buffered *(ebp+0x10) "fn ")
20790     8b/-> *(ebp+0xc) 0/r32/eax
20791     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20792     (write-buffered *(ebp+0x10) %eax)
20793     (write-buffered *(ebp+0x10) ": stmt copy-to: '")
20794     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
20795     (lookup *eax *(eax+4))  # Var-name Var-name => eax
20796     (write-buffered *(ebp+0x10) %eax)
20797     (write-buffered *(ebp+0x10) "' is too large to copy\n")
20798     (flush *(ebp+0x10))
20799     (stop *(ebp+0x14) 1)
20800     # never gets here
20801 
20802 check-mu-compare-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
20803     # . prologue
20804     55/push-ebp
20805     89/<- %ebp 4/r32/esp
20806     # . save registers
20807     50/push-eax
20808     51/push-ecx
20809     52/push-edx
20810     53/push-ebx
20811     56/push-esi
20812     57/push-edi
20813     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
20814     81 5/subop/subtract %esp 0x60/imm32
20815     68/push 0x60/imm32/size
20816     68/push 0/imm32/read
20817     68/push 0/imm32/write
20818     89/<- %edx 4/r32/esp
20819     # esi = stmt
20820     8b/-> *(ebp+8) 6/r32/esi
20821 $check-mu-compare-stmt:check-for-output:
20822     # if stmt->outputs abort
20823     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
20824     3d/compare-eax-and 0/imm32
20825     0f 85/jump-if-!= $check-mu-compare-stmt:error-too-many-outputs/disp32
20826 $check-mu-compare-stmt:get-left:
20827     # var left/edi: (addr stmt-var) = stmt->inouts
20828     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
20829     89/<- %edi 0/r32/eax
20830     # zero inouts
20831     3d/compare-eax-and 0/imm32
20832     0f 84/jump-if-= $check-mu-compare-stmt:error-incorrect-inouts/disp32
20833 $check-mu-compare-stmt:get-right:
20834     # var right/esi: (addr stmt-var) = left->next
20835     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
20836     89/<- %esi 0/r32/eax
20837     # 1 inout
20838     3d/compare-eax-and 0/imm32
20839     0f 84/jump-if-= $check-mu-compare-stmt:error-incorrect-inouts/disp32
20840     # > 2 inouts
20841     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
20842     3d/compare-eax-and 0/imm32
20843     0f 85/jump-if-!= $check-mu-compare-stmt:error-incorrect-inouts/disp32
20844     # if both inouts are in memory, abort
20845     {
20846 $check-mu-compare-stmt:both-in-mem:
20847       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
20848       (lookup *(eax+0x8) *(eax+0xc))  # Var-type Var-type => eax
20849       (is-simple-mu-type? %eax 0)  # => eax
20850       3d/compare-eax-and 0/imm32
20851       0f 85/jump-if-!= break/disp32
20852       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
20853       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
20854       3d/compare-eax-and 0/imm32
20855       75/jump-if-!= break/disp8
20856       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
20857       (lookup *(eax+0x8) *(eax+0xc))  # Var-type Var-type => eax
20858       (is-simple-mu-type? %eax 0)  # => eax
20859       3d/compare-eax-and 0/imm32
20860       75/jump-if-!= break/disp8
20861       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
20862       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
20863       3d/compare-eax-and 0/imm32
20864       75/jump-if-!= break/disp8
20865       e9/jump $check-mu-compare-stmt:error-both-in-memory/disp32
20866     }
20867 $check-mu-compare-stmt:types:
20868     # var right-type/ecx: (addr type-tree) = right->value->type
20869     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
20870     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20871     89/<- %ecx 0/r32/eax
20872     # if (right->is-deref?) right-type = right-type->payload
20873     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
20874     3d/compare-eax-and 0/imm32/false
20875     {
20876       74/jump-if-= break/disp8
20877       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
20878       # if right-type->right is null, right-type = right-type->left
20879       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
20880       {
20881         75/jump-if-!= break/disp8
20882         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
20883       }
20884       89/<- %ecx 0/r32/eax
20885     }
20886     # if right is not a scalar, abort
20887     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
20888     (size-of %eax)  # => eax
20889     3d/compare-eax-and 4/imm32
20890     0f 8f/jump-if-> $check-mu-compare-stmt:error-right-too-large/disp32
20891     # if left is not a scalar, abort
20892     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
20893     (size-of %eax)  # => eax
20894     3d/compare-eax-and 4/imm32
20895     0f 8f/jump-if-> $check-mu-compare-stmt:error-left-too-large/disp32
20896     # var left-type/ebx: (addr type-tree) = left->value->type
20897     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
20898     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20899     89/<- %ebx 0/r32/eax
20900     # if (left->is-deref?) left-type = left-type->payload
20901     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
20902     3d/compare-eax-and 0/imm32/false
20903     {
20904       74/jump-if-= break/disp8
20905       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
20906       # if left-type->right is null, left-type = left-type->left
20907       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
20908       {
20909         75/jump-if-!= break/disp8
20910         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
20911       }
20912       89/<- %ebx 0/r32/eax
20913     }
20914     # if (left-type == right-type) return
20915     (type-match? %ebx %ecx %edx)  # => eax
20916     3d/compare-eax-and 0/imm32
20917     0f 85/jump-if-!= $check-mu-compare-stmt:end/disp32
20918     # if left is an addr and right is 0, return
20919     {
20920       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
20921       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
20922       (is-mu-addr-type? %eax)  # => eax
20923       3d/compare-eax-and 0/imm32/false
20924       74/jump-if-= break/disp8
20925       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
20926       (lookup *eax *(eax+4))  # Var-name Var-name => eax
20927       (string-equal? %eax "0")  # => eax
20928       3d/compare-eax-and 0/imm32/false
20929       74/jump-if-= break/disp8
20930       eb/jump $check-mu-compare-stmt:end/disp8
20931     }
20932     # if left is not number-like, abort
20933     (check-mu-numberlike-arg %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
20934 $check-mu-compare-stmt:end:
20935     # . reclaim locals
20936     81 0/subop/add %esp 0x6c/imm32
20937     # . restore registers
20938     5f/pop-to-edi
20939     5e/pop-to-esi
20940     5b/pop-to-ebx
20941     5a/pop-to-edx
20942     59/pop-to-ecx
20943     58/pop-to-eax
20944     # . epilogue
20945     89/<- %esp 5/r32/ebp
20946     5d/pop-to-ebp
20947     c3/return
20948 
20949 $check-mu-compare-stmt:error-incorrect-inouts:
20950     (write-buffered *(ebp+0x10) "fn ")
20951     8b/-> *(ebp+0xc) 0/r32/eax
20952     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20953     (write-buffered *(ebp+0x10) %eax)
20954     (write-buffered *(ebp+0x10) ": stmt 'compare' must have two inouts\n")
20955     (flush *(ebp+0x10))
20956     (stop *(ebp+0x14) 1)
20957     # never gets here
20958 
20959 $check-mu-compare-stmt:error-too-many-outputs:
20960     (write-buffered *(ebp+0x10) "fn ")
20961     8b/-> *(ebp+0xc) 0/r32/eax
20962     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20963     (write-buffered *(ebp+0x10) %eax)
20964     (write-buffered *(ebp+0x10) ": stmt 'compare' must not have any outputs\n")
20965     (flush *(ebp+0x10))
20966     (stop *(ebp+0x14) 1)
20967     # never gets here
20968 
20969 $check-mu-compare-stmt:error-both-in-memory:
20970     (write-buffered *(ebp+0x10) "fn ")
20971     8b/-> *(ebp+0xc) 0/r32/eax
20972     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20973     (write-buffered *(ebp+0x10) %eax)
20974     (write-buffered *(ebp+0x10) ": stmt compare: both inouts are in memory\n")
20975     (flush *(ebp+0x10))
20976     (stop *(ebp+0x14) 1)
20977     # never gets here
20978 
20979 $check-mu-compare-stmt:error-left-too-large:
20980     (write-buffered *(ebp+0x10) "fn ")
20981     8b/-> *(ebp+0xc) 0/r32/eax
20982     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20983     (write-buffered *(ebp+0x10) %eax)
20984     (write-buffered *(ebp+0x10) ": stmt compare: '")
20985     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
20986     (lookup *eax *(eax+4))  # Var-name Var-name => eax
20987     (write-buffered *(ebp+0x10) %eax)
20988     (write-buffered *(ebp+0x10) "' is too large to compare\n")
20989     (flush *(ebp+0x10))
20990     (stop *(ebp+0x14) 1)
20991     # never gets here
20992 
20993 $check-mu-compare-stmt:error-right-too-large:
20994     (write-buffered *(ebp+0x10) "fn ")
20995     8b/-> *(ebp+0xc) 0/r32/eax
20996     (lookup *eax *(eax+4))  # Function-name Function-name => eax
20997     (write-buffered *(ebp+0x10) %eax)
20998     (write-buffered *(ebp+0x10) ": stmt compare: '")
20999     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
21000     (lookup *eax *(eax+4))  # Var-name Var-name => eax
21001     (write-buffered *(ebp+0x10) %eax)
21002     (write-buffered *(ebp+0x10) "' is too large to compare\n")
21003     (flush *(ebp+0x10))
21004     (stop *(ebp+0x14) 1)
21005     # never gets here
21006 
21007 check-mu-address-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21008     # . prologue
21009     55/push-ebp
21010     89/<- %ebp 4/r32/esp
21011     # . save registers
21012     50/push-eax
21013     51/push-ecx
21014     52/push-edx
21015     56/push-esi
21016     57/push-edi
21017 $check-mu-address-stmt:get-output:
21018     # esi = stmt
21019     8b/-> *(ebp+8) 6/r32/esi
21020     # var output/edi: (addr stmt-var) = stmt->outputs
21021     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
21022     89/<- %edi 0/r32/eax
21023     # zero outputs
21024     3d/compare-eax-and 0/imm32
21025     0f 84/jump-if-= $check-mu-address-stmt:error-no-output/disp32
21026     # > 1 output
21027     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
21028     3d/compare-eax-and 0/imm32
21029     0f 85/jump-if-!= $check-mu-address-stmt:error-too-many-outputs/disp32
21030 $check-mu-address-stmt:get-inout:
21031     # var inout/esi: (addr stmt-var) = stmt->inouts
21032     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21033     89/<- %esi 0/r32/eax
21034     # zero inouts
21035     3d/compare-eax-and 0/imm32
21036     0f 84/jump-if-= $check-mu-address-stmt:error-no-inout/disp32
21037     # > 1 inout
21038     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
21039     3d/compare-eax-and 0/imm32
21040     0f 85/jump-if-!= $check-mu-address-stmt:error-too-many-inouts/disp32
21041 $check-mu-address-stmt:types:
21042     # if output not in register, abort
21043     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
21044     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
21045     3d/compare-eax-and 0/imm32
21046     0f 84/jump-if-= $check-mu-address-stmt:error-output-not-in-register/disp32
21047     # var output-type/edx: (addr type-tree) = output->value->type
21048     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
21049     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
21050     89/<- %edx 0/r32/eax
21051     # if output-type not an addr, abort
21052     (is-mu-addr-type? %edx)  # => eax
21053     3d/compare-eax-and 0/imm32/false
21054     0f 84/jump-if-= $check-mu-address-stmt:error-output-not-address/disp32
21055     # output-type = output-type->right
21056     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
21057     # if output-type->right is null, output-type = output-type->left
21058     81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
21059     {
21060       75/jump-if-!= break/disp8
21061       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
21062     }
21063     89/<- %edx 0/r32/eax
21064     # var inout-type/ecx: (addr type-tree) = inout->value->type
21065     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
21066     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
21067     89/<- %ecx 0/r32/eax
21068     # if (inout->is-deref?) inout-type = inout-type->payload
21069     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
21070     3d/compare-eax-and 0/imm32/false
21071     {
21072       74/jump-if-= break/disp8
21073       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
21074       # if inout-type->right is null, t = inout-type->left
21075       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
21076       {
21077         75/jump-if-!= break/disp8
21078         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
21079       }
21080       89/<- %ecx 0/r32/eax
21081     }
21082     # if (inout-type != output-type) abort
21083     (type-equal-ignoring-capacity? %edx %ecx)  # => eax
21084     3d/compare-eax-and 0/imm32
21085     0f 84/jump-if-= $check-mu-address-stmt:error-type-mismatch/disp32
21086 $check-mu-address-stmt:end:
21087     # . restore registers
21088     5f/pop-to-edi
21089     5e/pop-to-esi
21090     5a/pop-to-edx
21091     59/pop-to-ecx
21092     58/pop-to-eax
21093     # . epilogue
21094     89/<- %esp 5/r32/ebp
21095     5d/pop-to-ebp
21096     c3/return
21097 
21098 $check-mu-address-stmt:error-no-inout:
21099     (write-buffered *(ebp+0x10) "fn ")
21100     8b/-> *(ebp+0xc) 0/r32/eax
21101     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21102     (write-buffered *(ebp+0x10) %eax)
21103     (write-buffered *(ebp+0x10) ": stmt 'address' expects an inout\n")
21104     (flush *(ebp+0x10))
21105     (stop *(ebp+0x14) 1)
21106     # never gets here
21107 
21108 $check-mu-address-stmt:error-too-many-inouts:
21109     (write-buffered *(ebp+0x10) "fn ")
21110     8b/-> *(ebp+0xc) 0/r32/eax
21111     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21112     (write-buffered *(ebp+0x10) %eax)
21113     (write-buffered *(ebp+0x10) ": stmt 'address' must have just one inout\n")
21114     (flush *(ebp+0x10))
21115     (stop *(ebp+0x14) 1)
21116     # never gets here
21117 
21118 $check-mu-address-stmt:error-no-output:
21119     (write-buffered *(ebp+0x10) "fn ")
21120     8b/-> *(ebp+0xc) 0/r32/eax
21121     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21122     (write-buffered *(ebp+0x10) %eax)
21123     (write-buffered *(ebp+0x10) ": stmt 'address' expects an output\n")
21124     (flush *(ebp+0x10))
21125     (stop *(ebp+0x14) 1)
21126     # never gets here
21127 
21128 $check-mu-address-stmt:error-output-not-in-register:
21129     (write-buffered *(ebp+0x10) "fn ")
21130     8b/-> *(ebp+0xc) 0/r32/eax
21131     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21132     (write-buffered *(ebp+0x10) %eax)
21133     (write-buffered *(ebp+0x10) ": stmt address: output '")
21134     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
21135     (lookup *eax *(eax+4))  # Var-name Var-name => eax
21136     (write-buffered *(ebp+0x10) %eax)
21137     (write-buffered *(ebp+0x10) "' not in a register\n")
21138     (flush *(ebp+0x10))
21139     (stop *(ebp+0x14) 1)
21140     # never gets here
21141 
21142 $check-mu-address-stmt:error-too-many-outputs:
21143     (write-buffered *(ebp+0x10) "fn ")
21144     8b/-> *(ebp+0xc) 0/r32/eax
21145     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21146     (write-buffered *(ebp+0x10) %eax)
21147     (write-buffered *(ebp+0x10) ": stmt 'address' must have just one output\n")
21148     (flush *(ebp+0x10))
21149     (stop *(ebp+0x14) 1)
21150     # never gets here
21151 
21152 $check-mu-address-stmt:error-output-not-address:
21153     (write-buffered *(ebp+0x10) "fn ")
21154     8b/-> *(ebp+0xc) 0/r32/eax
21155     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21156     (write-buffered *(ebp+0x10) %eax)
21157     (write-buffered *(ebp+0x10) ": stmt address: output '")
21158     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
21159     (lookup *eax *(eax+4))  # Var-name Var-name => eax
21160     (write-buffered *(ebp+0x10) %eax)
21161     (write-buffered *(ebp+0x10) "' is not an addr\n")
21162     (flush *(ebp+0x10))
21163     (stop *(ebp+0x14) 1)
21164     # never gets here
21165 
21166 $check-mu-address-stmt:error-type-mismatch:
21167     (write-buffered *(ebp+0x10) "fn ")
21168     8b/-> *(ebp+0xc) 0/r32/eax
21169     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21170     (write-buffered *(ebp+0x10) %eax)
21171     (write-buffered *(ebp+0x10) ": stmt address: output '")
21172     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
21173     (lookup *eax *(eax+4))  # Var-name Var-name => eax
21174     (write-buffered *(ebp+0x10) %eax)
21175     (write-buffered *(ebp+0x10) "' cannot hold address of '")
21176     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
21177     (lookup *eax *(eax+4))  # Var-name Var-name => eax
21178     (write-buffered *(ebp+0x10) %eax)
21179     (write-buffered *(ebp+0x10) "'\n")
21180     (flush *(ebp+0x10))
21181     (stop *(ebp+0x14) 1)
21182     # never gets here
21183 
21184 type-equal-ignoring-capacity?:  # a: (addr type-tree), b: (addr type-tree) -> result/eax: boolean
21185     # . prologue
21186     55/push-ebp
21187     89/<- %ebp 4/r32/esp
21188     # . save registers
21189     51/push-ecx
21190     52/push-edx
21191     53/push-ebx
21192     # var curr-a/ecx: (addr type-tree) = a
21193     8b/-> *(ebp+8) 1/r32/ecx
21194     # var curr-b/ebx: (addr type-tree) = b
21195     8b/-> *(ebp+0xc) 3/r32/ebx
21196     # if (curr-a->is-atom?) fall back to regular equality
21197     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
21198     0f 85/jump-if-!= $type-equal-ignoring-capacity?:base-case/disp32
21199     # if (curr-a->left != curr-b->left) return false
21200     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
21201     89/<- %edx 0/r32/eax
21202     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
21203     (type-equal? %edx %eax)  # => eax
21204     3d/compare-eax-and 0/imm32/false
21205     0f 84/jump-if-= $type-equal-ignoring-capacity?:end/disp32  # eax switches meaning
21206     # if (curr-a->left == "array") curr-a = curr-a->element-type
21207     {
21208       (is-mu-array? %edx)  # => eax
21209       3d/compare-eax-and 0/imm32/false
21210       75/jump-if-!= break/disp8
21211 $type-equal-ignoring-capacity?:array:
21212       # curr-a = curr-a->right->left
21213       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
21214       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
21215       89/<- %ecx 0/r32/eax
21216       # curr-b = curr-b->right->left
21217       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
21218       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
21219       89/<- %ebx 0/r32/eax
21220       eb/jump $type-equal-ignoring-capacity?:base-case/disp8
21221     }
21222     # if (curr-a->left == "stream") curr-a = curr-a->element-type
21223     {
21224       (is-mu-stream? %edx)  # => eax
21225       3d/compare-eax-and 0/imm32/false
21226       75/jump-if-!= break/disp8
21227 $type-equal-ignoring-capacity?:stream:
21228       # curr-a = curr-a->right->left
21229       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
21230       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
21231       89/<- %ecx 0/r32/eax
21232       # curr-b = curr-b->right->left
21233       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
21234       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
21235       89/<- %ebx 0/r32/eax
21236       eb/jump $type-equal-ignoring-capacity?:base-case/disp8
21237     }
21238 $type-equal-ignoring-capacity?:base-case:
21239     # return type-equal?(curr-a, curr-b)
21240     (type-equal? %ecx %ebx)  # => eax
21241 $type-equal-ignoring-capacity?:end:
21242     # . restore registers
21243     5b/pop-to-ebx
21244     5a/pop-to-edx
21245     59/pop-to-ecx
21246     # . epilogue
21247     89/<- %esp 5/r32/ebp
21248     5d/pop-to-ebp
21249     c3/return
21250 
21251 check-mu-return-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21252     # . prologue
21253     55/push-ebp
21254     89/<- %ebp 4/r32/esp
21255     # . save registers
21256     50/push-eax
21257     51/push-ecx
21258     52/push-edx
21259     53/push-ebx
21260     56/push-esi
21261     57/push-edi
21262     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
21263     81 5/subop/subtract %esp 0x60/imm32
21264     68/push 0x60/imm32/size
21265     68/push 0/imm32/read
21266     68/push 0/imm32/write
21267     89/<- %edx 4/r32/esp
21268     # var template/esi: (addr list var) = fn->outputs
21269     8b/-> *(ebp+0xc) 0/r32/eax
21270     (lookup *(eax+0x10) *(eax+0x14))  # Function-outputs Function-outputs => eax
21271     89/<- %esi 0/r32/eax
21272     # var curr-template/ebx: (addr list var) = fn->outputs
21273     89/<- %ebx 0/r32/eax
21274     # var curr/edi: (addr stmt-var) = stmt->inouts
21275     8b/-> *(ebp+8) 0/r32/eax
21276     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21277     89/<- %edi 0/r32/eax
21278     {
21279       # if template is null, break
21280       81 7/subop/compare %ebx 0/imm32
21281       0f 84/jump-if-= break/disp32
21282       # if curr is null, abort
21283       81 7/subop/compare %edi 0/imm32
21284       0f 84/jump-if-= $check-mu-return-stmt:error-too-few-inouts/disp32
21285       # var template-type/ecx: (addr type-tree) = template->value->type
21286       (lookup *ebx *(ebx+4))  # List-value List-value => eax
21287       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
21288       89/<- %ecx 0/r32/eax
21289       # var curr-type/eax: (addr type-tree) = curr->value->type
21290       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
21291       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
21292       # if (curr->is-deref?) curr-type = payload of curr-type
21293       81 7/subop/compare *(edi+0x10) 0/imm32/false  # Stmt-var-is-deref
21294       {
21295         74/jump-if-= break/disp8
21296         (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
21297         # if t->right is null, t = t->left
21298         81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
21299         75/jump-if-!= break/disp8
21300         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
21301       }
21302       # if (curr-type != template-type) abort
21303       (type-match? %ecx %eax %edx)  # => eax
21304       3d/compare-eax-and 0/imm32/false
21305       0f 84/jump-if-= $check-mu-return-stmt:error1/disp32
21306       # if register-within-list-with-conflict?(curr, original template, curr-template, stmt) abort
21307       (register-within-list-with-conflict? %edi %esi %ebx *(ebp+8))  # => eax
21308       3d/compare-eax-and 0/imm32/false
21309       0f 85/jump-if-!= $check-mu-return-stmt:error2/disp32
21310       # template = template->next
21311       (lookup *(ebx+8) *(ebx+0xc))  # List-next List-next => eax
21312       89/<- %ebx 0/r32/eax
21313       # curr = curr->next
21314       (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
21315       89/<- %edi 0/r32/eax
21316       #
21317       e9/jump loop/disp32
21318     }
21319     # if curr is not null, abort
21320     81 7/subop/compare %edi 0/imm32
21321     0f 85/jump-if-!= $check-mu-return-stmt:error-too-many-inouts/disp32
21322 $check-mu-return-stmt:end:
21323     # . reclaim locals
21324     81 0/subop/add %esp 0x6c/imm32
21325     # . restore registers
21326     5f/pop-to-edi
21327     5e/pop-to-esi
21328     5b/pop-to-ebx
21329     5a/pop-to-edx
21330     59/pop-to-ecx
21331     58/pop-to-eax
21332     # . epilogue
21333     89/<- %esp 5/r32/ebp
21334     5d/pop-to-ebp
21335     c3/return
21336 
21337 $check-mu-return-stmt:error1:
21338     (write-buffered *(ebp+0x10) "fn ")
21339     8b/-> *(ebp+0xc) 0/r32/eax
21340     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21341     (write-buffered *(ebp+0x10) %eax)
21342     (write-buffered *(ebp+0x10) ": return: '")
21343     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
21344     (lookup *eax *(eax+4))  # Var-name Var-name => eax
21345     (write-buffered *(ebp+0x10) %eax)
21346     (write-buffered *(ebp+0x10) "' has the wrong type\n")
21347     (flush *(ebp+0x10))
21348     (stop *(ebp+0x14) 1)
21349     # never gets here
21350 
21351 $check-mu-return-stmt:error2:
21352     (write-buffered *(ebp+0x10) "fn ")
21353     8b/-> *(ebp+0xc) 0/r32/eax
21354     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21355     (write-buffered *(ebp+0x10) %eax)
21356     (write-buffered *(ebp+0x10) ": return: '")
21357     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
21358     (lookup *eax *(eax+4))  # Var-name Var-name => eax
21359     (write-buffered *(ebp+0x10) %eax)
21360     (write-buffered *(ebp+0x10) "' is no longer available\n")
21361     (flush *(ebp+0x10))
21362     (stop *(ebp+0x14) 1)
21363     # never gets here
21364 
21365 $check-mu-return-stmt:error-too-few-inouts:
21366     (write-buffered *(ebp+0x10) "fn ")
21367     8b/-> *(ebp+0xc) 0/r32/eax
21368     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21369     (write-buffered *(ebp+0x10) %eax)
21370     (write-buffered *(ebp+0x10) ": return: too few inouts\n")
21371     (flush *(ebp+0x10))
21372     (stop *(ebp+0x14) 1)
21373     # never gets here
21374 
21375 $check-mu-return-stmt:error-too-many-inouts:
21376     (write-buffered *(ebp+0x10) "fn ")
21377     8b/-> *(ebp+0xc) 0/r32/eax
21378     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21379     (write-buffered *(ebp+0x10) %eax)
21380     (write-buffered *(ebp+0x10) ": return: too many inouts\n")
21381     (flush *(ebp+0x10))
21382     (stop *(ebp+0x14) 1)
21383     # never gets here
21384 
21385 check-all-unique-registers:  # outputs: (addr list var), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21386     # . prologue
21387     55/push-ebp
21388     89/<- %ebp 4/r32/esp
21389     # . save registers
21390     50/push-eax
21391     51/push-ecx
21392     56/push-esi
21393     # var table/esi: (addr table (handle array byte) int 8)
21394     81 5/subop/subtract %esp 0x60/imm32
21395     68/push 0x60/imm32/size
21396     68/push 0/imm32/read
21397     68/push 0/imm32/write
21398     89/<- %esi 4/r32/esp
21399     # var curr/ecx: (addr list var) = outputs
21400     8b/-> *(ebp+8) 1/r32/ecx
21401     {
21402       # if (curr == 0) break
21403       81 7/subop/compare %ecx 0/imm32
21404       0f 84/jump-if-= break/disp32
21405       # var reg/eax: (addr array byte) = curr->value->register  # guaranteed to exist
21406       (lookup *ecx *(ecx+4))  # List-value List-value => eax
21407       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
21408       # if reg exists in table, abort
21409       (maybe-get %esi %eax 0xc)  # => eax
21410       3d/compare-eax-and 0/imm32
21411       0f 85/jump-if-!= $check-all-unique-registers:abort/disp32
21412       # insert reg in table
21413       (lookup *ecx *(ecx+4))  # List-value List-value => eax
21414       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
21415       (get-or-insert %esi %eax 0xc Heap)
21416       # curr = curr->next
21417       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
21418       89/<- %ecx 0/r32/eax
21419       e9/jump loop/disp32
21420     }
21421 $check-all-unique-registers:end:
21422     # . reclaim locals
21423     81 0/subop/add %esp 0x6c/imm32
21424     # . restore registers
21425     5e/pop-to-esi
21426     59/pop-to-ecx
21427     58/pop-to-eax
21428     # . epilogue
21429     89/<- %esp 5/r32/ebp
21430     5d/pop-to-ebp
21431     c3/return
21432 
21433 $check-all-unique-registers:abort:
21434     (write-buffered *(ebp+0x10) "fn ")
21435     8b/-> *(ebp+0xc) 0/r32/eax
21436     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21437     (write-buffered *(ebp+0x10) %eax)
21438     (write-buffered *(ebp+0x10) ": outputs must be in unique registers\n")
21439     (flush *(ebp+0x10))
21440     (stop *(ebp+0x14) 1)
21441     # never gets here
21442 
21443 # return false if s's register is not between start (inclusive) and end (exclusive)
21444 # return false if the positionally corresponding register in stmt->inouts (where s comes from) is also s's register
21445 # otherwise return true
21446 register-within-list-with-conflict?:  # s: (addr stmt-var), start: (addr list var), end: (addr list var), stmt: (addr stmt) -> result/eax: boolean
21447     # . prologue
21448     55/push-ebp
21449     89/<- %ebp 4/r32/esp
21450     # . save registers
21451     51/push-ecx
21452     52/push-edx
21453     53/push-ebx
21454     56/push-esi
21455     57/push-edi
21456     # var target/ebx: (addr array byte) = s->value->register
21457     8b/-> *(ebp+8) 0/r32/eax
21458     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
21459     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
21460 #?     (write-buffered Stderr "AA: ")
21461 #?     (write-buffered Stderr %eax)
21462 #?     (write-buffered Stderr Newline)
21463 #?     (flush Stderr)
21464     # if (var->register == 0) return false
21465     3d/compare-eax-and 0/imm32
21466     0f 84/jump-if-= $register-within-list-with-conflict?:end/disp32  # eax turns into result
21467     89/<- %ebx 0/r32/eax
21468     # var curr/ecx: (addr list var) = start
21469     8b/-> *(ebp+0xc) 1/r32/ecx
21470     # edx = end
21471     8b/-> *(ebp+0x10) 2/r32/edx
21472     {
21473       # if (curr == 0) break
21474       81 7/subop/compare %edi 0/imm32
21475       0f 84/jump-if-= break/disp32
21476       # if (curr == end) break
21477       39/compare %ecx 2/r32/edx
21478       0f 84/jump-if-= break/disp32
21479       # var curr-reg/eax: (addr array byte) = curr->value->register
21480       (lookup *ecx *(ecx+4))  # List-value List-value => eax
21481       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
21482       # if (curr-reg == 0) continue
21483       3d/compare-eax-and 0/imm32
21484       74/jump-if-= $register-within-list-with-conflict?:continue/disp8
21485       # if (curr-reg == target) check for conflict
21486       (string-equal? %eax %ebx)  # => eax
21487       3d/compare-eax-and 0/imm32/false
21488       {
21489         74/jump-if-= break/disp8
21490 #?         (write-buffered Stderr "conflict?\n")
21491 #?         (flush Stderr)
21492         # var return-inouts/eax: (addr stmt-var) = stmt->inouts
21493         8b/-> *(ebp+0x14) 0/r32/eax
21494         (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21495         (register-conflict? %ebx %eax *(ebp+0xc))  # => eax
21496         eb/jump $register-within-list-with-conflict?:end/disp8
21497       }
21498 $register-within-list-with-conflict?:continue:
21499       # curr = curr->next
21500       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
21501       89/<- %ecx 0/r32/eax
21502       e9/jump loop/disp32
21503     }
21504     # return false
21505     b8/copy-to-eax 0/imm32/false
21506 $register-within-list-with-conflict?:end:
21507     # . restore registers
21508     5f/pop-to-edi
21509     5e/pop-to-esi
21510     5b/pop-to-ebx
21511     5a/pop-to-edx
21512     59/pop-to-ecx
21513     # . epilogue
21514     89/<- %esp 5/r32/ebp
21515     5d/pop-to-ebp
21516     c3/return
21517 
21518 # At the first occurrence of register 'reg' in fn-outputs,
21519 # check if the corresponding element of return-inouts has a different register.
21520 # This hacky helper is intended to be called in one specific place. Don't
21521 # reuse it as is.
21522 register-conflict?:  # reg: (addr array byte), return-inouts: (addr stmt-var), fn-outputs: (addr list var) => result/eax: boolean
21523     # . prologue
21524     55/push-ebp
21525     89/<- %ebp 4/r32/esp
21526     # . save registers
21527     51/push-ecx
21528     52/push-edx
21529     53/push-ebx
21530     56/push-esi
21531     57/push-edi
21532 #?     (write-buffered Stderr "BB: ")
21533 #?     (write-buffered Stderr *(ebp+8))
21534 #?     (write-buffered Stderr Newline)
21535 #?     (flush Stderr)
21536     # var curr-output/edi: (addr list var) = fn-outputs
21537     8b/-> *(ebp+0x10) 7/r32/edi
21538     # var curr-inout/esi: (addr stmt-var) = return-inouts
21539     8b/-> *(ebp+0xc) 6/r32/esi
21540     {
21541       # if (curr-output == 0) abort
21542       81 7/subop/compare %edi 0/imm32
21543       0f 84/jump-if-= break/disp32
21544       # if (curr-output->value->register != reg) continue
21545       (lookup *edi *(edi+4))  # List-value List-value => eax
21546       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
21547       (string-equal? %eax *(ebp+8))  # => eax
21548       3d/compare-eax-and 0/imm32/false
21549       0f 84/jump-if= $register-conflict?:continue/disp32
21550 #?       (write-buffered Stderr "rescan\n")
21551 #?       (flush Stderr)
21552       # var curr-reg/eax: (addr array byte) = curr-inout->value->register
21553       (lookup *esi *(esi+4))  # List-value List-value => eax
21554       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
21555       # if (curr-reg == 0) return true
21556       3d/compare-eax-and 0/imm32
21557       {
21558         75/jump-if-!= break/disp8
21559 #?         (write-buffered Stderr "no register\n")
21560 #?         (flush Stderr)
21561         b8/copy-to-eax 1/imm32/true
21562         e9/jump $register-conflict?:end/disp32
21563       }
21564       # return (curr-reg != reg)
21565       (string-equal? %eax *(ebp+8))  # => eax
21566       3d/compare-eax-and 0/imm32/false
21567       0f 94/set-if-= %al
21568 #?       (write-buffered Stderr "final: ")
21569 #?       (write-int32-hex-buffered Stderr %eax)
21570 #?       (write-buffered Stderr Newline)
21571 #?       (flush Stderr)
21572       eb/jump $register-conflict?:end/disp8
21573 $register-conflict?:continue:
21574       # curr-output = curr-output->next
21575       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
21576       89/<- %edi 0/r32/eax
21577       # curr-inout = curr-inout->next
21578       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
21579       89/<- %esi 0/r32/eax
21580       e9/jump loop/disp32
21581     }
21582     # should never get here
21583     (write-buffered Stderr "register-conflict? misused\n")
21584     (flush Stderr)
21585     e8/call syscall_exit/disp32
21586 $register-conflict?:end:
21587     # . restore registers
21588     5f/pop-to-edi
21589     5e/pop-to-esi
21590     5b/pop-to-ebx
21591     5a/pop-to-edx
21592     59/pop-to-ecx
21593     # . epilogue
21594     89/<- %esp 5/r32/ebp
21595     5d/pop-to-ebp
21596     c3/return
21597 
21598 check-final-stmt-is-return:  # block: (addr block), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21599     # . prologue
21600     55/push-ebp
21601     89/<- %ebp 4/r32/esp
21602     # . save registers
21603     50/push-eax
21604     51/push-ecx
21605     # var curr/ecx: (addr list stmt) = block->stmts
21606     8b/-> *(ebp+8) 0/r32/eax
21607     (lookup *(eax+4) *(eax+8))  # Block-stmts Block-stmts => eax
21608     3d/compare-eax-and 0/imm32
21609     74/jump-if-= $check-final-stmt-is-return:end/disp8
21610     89/<- %ecx 0/r32/eax
21611     {
21612       # if curr->next == 0, break
21613       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
21614       3d/compare-eax-and 0/imm32
21615       74/jump-if-= break/disp8
21616       # curr = curr->next
21617       89/<- %ecx 0/r32/eax
21618       e9/jump loop/disp32
21619     }
21620 $check-final-stmt-is-return:check-tag:
21621     # if curr->value->tag != Stmt1, abort
21622     (lookup *ecx *(ecx+4))  # List-value List-value => eax
21623     81 7/subop/compare *eax 1/imm32/stmt1  # Stmt-tag
21624     75/jump-if-!= $check-final-stmt-is-return:error/disp8
21625 $check-final-stmt-is-return:check-operation:
21626     # if curr->operation != "return", abort
21627     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
21628     (string-equal? %eax "return")
21629     3d/compare-eax-and 0/imm32/false
21630     74/jump-if-= $check-final-stmt-is-return:error/disp8
21631 $check-final-stmt-is-return:end:
21632     # . restore registers
21633     59/pop-to-ecx
21634     58/pop-to-eax
21635     # . epilogue
21636     89/<- %esp 5/r32/ebp
21637     5d/pop-to-ebp
21638     c3/return
21639 
21640 $check-final-stmt-is-return:error:
21641     (write-buffered *(ebp+0x10) "fn ")
21642     8b/-> *(ebp+0xc) 0/r32/eax
21643     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21644     (write-buffered *(ebp+0x10) %eax)
21645     (write-buffered *(ebp+0x10) ": final statement should be a 'return'\n")
21646     (flush *(ebp+0x10))
21647     (stop *(ebp+0x14) 1)
21648     # never gets here
21649 
21650 check-no-breaks:  # block: (addr block), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21651     # . prologue
21652     55/push-ebp
21653     89/<- %ebp 4/r32/esp
21654     # . save registers
21655     50/push-eax
21656     51/push-ecx
21657     # var curr/ecx: (addr list stmt) = block->stmts
21658     8b/-> *(ebp+8) 0/r32/eax
21659     (lookup *(eax+4) *(eax+8))  # Block-stmts Block-stmts => eax
21660     3d/compare-eax-and 0/imm32
21661     0f 84/jump-if-= $check-no-breaks:end/disp32
21662     89/<- %ecx 0/r32/eax
21663     {
21664       # if curr->next == 0, break
21665       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
21666       3d/compare-eax-and 0/imm32
21667       74/jump-if-= break/disp8
21668       # if curr->value->tag != Stmt1, continue
21669       (lookup *ecx *(ecx+4))  # List-value List-value => eax
21670       81 7/subop/compare *eax 1/imm32/stmt1  # Stmt-tag
21671       75/jump-if-!= $check-no-breaks:continue/disp8
21672       # if curr->value->operation starts with "break", abort
21673       (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
21674       (string-starts-with? %eax "break")  # => eax
21675       3d/compare-eax-and 0/imm32/false
21676       75/jump-if-!= $check-no-breaks:error/disp8
21677 $check-no-breaks:continue:
21678       # curr = curr->next
21679       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
21680       89/<- %ecx 0/r32/eax
21681       e9/jump loop/disp32
21682     }
21683 $check-no-breaks:end:
21684     # . restore registers
21685     59/pop-to-ecx
21686     58/pop-to-eax
21687     # . epilogue
21688     89/<- %esp 5/r32/ebp
21689     5d/pop-to-ebp
21690     c3/return
21691 
21692 $check-no-breaks:error:
21693     (write-buffered *(ebp+0x10) "fn ")
21694     8b/-> *(ebp+0xc) 0/r32/eax
21695     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21696     (write-buffered *(ebp+0x10) %eax)
21697     (write-buffered *(ebp+0x10) " has outputs, so you cannot 'break' out of the outermost block. Use 'return'.\n")
21698     (flush *(ebp+0x10))
21699     (stop *(ebp+0x14) 1)
21700     # never gets here
21701 
21702 check-mu-get-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21703     # . prologue
21704     55/push-ebp
21705     89/<- %ebp 4/r32/esp
21706     # . save registers
21707     50/push-eax
21708     51/push-ecx
21709     52/push-edx
21710     53/push-ebx
21711     56/push-esi
21712     57/push-edi
21713     # esi = stmt
21714     8b/-> *(ebp+8) 6/r32/esi
21715     # - check for 0 inouts
21716     # var base/ecx: (addr var) = stmt->inouts->value
21717     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21718     3d/compare-eax-and 0/imm32/false
21719     0f 84/jump-if-= $check-mu-get-stmt:error-too-few-inouts/disp32
21720     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
21721     89/<- %ecx 0/r32/eax
21722 $check-mu-get-stmt:check-base:
21723     # - check base type
21724     # if it's an 'addr', check that it's in a register
21725     # var base-type/ebx: (addr type-tree) = lookup(base->type)
21726     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
21727     89/<- %ebx 0/r32/eax
21728     {
21729       81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
21730       0f 85/jump-if-!= break/disp32
21731 $check-mu-get-stmt:base-is-compound:
21732       # if (type->left != addr) break
21733       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
21734       (is-simple-mu-type? %eax 2)  # addr => eax
21735       3d/compare-eax-and 0/imm32/false
21736       74/jump-if-= break/disp8
21737 $check-mu-get-stmt:base-is-addr:
21738       # now check for register
21739       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
21740       0f 84/jump-if-= $check-mu-get-stmt:error-base-type-addr-but-not-register/disp32
21741 $check-mu-get-stmt:base-is-addr-in-register:
21742       # type->left is now an addr; skip it
21743       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
21744       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
21745       0f 85/jump-if-!= $check-mu-get-stmt:error-bad-base/disp32
21746 $check-mu-get-stmt:base-is-addr-to-atom-in-register:
21747       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
21748       89/<- %ebx 0/r32/eax
21749     }
21750 $check-mu-get-stmt:check-base-typeinfo:
21751     # ensure type is a container
21752     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
21753     {
21754       75/jump-if-!= break/disp8
21755       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
21756       89/<- %ebx 0/r32/eax
21757     }
21758     # var base-type-id/ebx: type-id = base-type->value
21759     8b/-> *(ebx+4) 3/r32/ebx  # Type-tree-value
21760     (is-container? %ebx)  # => eax
21761     3d/compare-eax-and 0/imm32/false
21762     0f 84/jump-if-= $check-mu-get-stmt:error-bad-base/disp32
21763     # var base-typeinfo/edx: (addr typeinfo) = find-typeinfo(base-type-id)
21764     # . var container/ecx: (handle typeinfo)
21765     68/push 0/imm32
21766     68/push 0/imm32
21767     89/<- %ecx 4/r32/esp
21768     # .
21769     (find-typeinfo %ebx %ecx)
21770     (lookup *ecx *(ecx+4))  # => eax
21771     # . reclaim container
21772     81 0/subop/add %esp 8/imm32
21773     # .
21774     89/<- %edx 0/r32/eax
21775     # var offset/ecx: (addr stmt-var) = stmt->inouts->next
21776     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21777     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
21778     89/<- %ecx 0/r32/eax
21779     # - check for 1 inout
21780     3d/compare-eax-and 0/imm32/false
21781     0f 84/jump-if-= $check-mu-get-stmt:error-too-few-inouts/disp32
21782     # var offset/ecx: (addr var) = lookup(offset->value)
21783     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
21784     89/<- %ecx 0/r32/eax
21785     # - check for valid field
21786     81 7/subop/compare *(ecx+0x14) -1/imm32/uninitialized  # Var-offset
21787     0f 84/jump-if-= $check-mu-get-stmt:error-bad-field/disp32
21788     # - check for too many inouts
21789     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21790     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
21791     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
21792     3d/compare-eax-and 0/imm32/false
21793     0f 85/jump-if-!= $check-mu-get-stmt:error-too-many-inouts/disp32
21794     # var output/edi: (addr var) = stmt->outputs->value
21795     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
21796     # - check for 0 outputs
21797     3d/compare-eax-and 0/imm32/false
21798     0f 84/jump-if-= $check-mu-get-stmt:error-too-few-outputs/disp32
21799     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
21800     89/<- %edi 0/r32/eax
21801 $check-mu-get-stmt:check-output-type:
21802     # - check output type
21803     # must be in register
21804     (lookup *(edi+0x18) *(edi+0x1c))  # Var-register Var-register => eax
21805     3d/compare-eax-and 0/imm32
21806     0f 84/jump-if-= $check-mu-get-stmt:error-output-not-in-register/disp32
21807     # must have a non-atomic type
21808     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
21809     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
21810     0f 85/jump-if-!= $check-mu-get-stmt:error-output-type-not-address/disp32
21811     # type must start with (addr ...)
21812     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
21813     (is-simple-mu-type? %eax 2)  # => eax
21814     3d/compare-eax-and 0/imm32/false
21815     0f 84/jump-if-= $check-mu-get-stmt:error-output-type-not-address/disp32
21816 $check-mu-get-stmt:check-output-type-match:
21817     # payload of addr type must match 'type' definition
21818     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
21819     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
21820     # if (payload->right == null) payload = payload->left
21821     81 7/subop/compare *(eax+0xc) 0/imm32/null  # Type-tree-right
21822     {
21823       75/jump-if-!= break/disp8
21824       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
21825     }
21826     89/<- %edi 0/r32/eax
21827     # . var output-name/ecx: (addr array byte)
21828     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
21829     89/<- %ecx 0/r32/eax
21830     # . var base-typeinfo-entry/eax: (addr handle typeinfo-entry)
21831     (lookup *(edx+4) *(edx+8))  # Typeinfo-fields Typeinfo-fields => eax
21832     (get %eax %ecx 0x10)  # => eax
21833     # .
21834     (lookup *eax *(eax+4))  # => eax
21835     (lookup *eax *(eax+4))  # Typeinfo-entry-input-var Typeinfo-entry-input-var => eax
21836     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
21837     # .
21838     (type-equal? %edi %eax)  # => eax
21839     3d/compare-eax-and 0/imm32/false
21840     0f 84/jump-if-= $check-mu-get-stmt:error-bad-output-type/disp32
21841     # - check for too many outputs
21842     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
21843     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
21844     3d/compare-eax-and 0/imm32/false
21845     0f 85/jump-if-!= $check-mu-get-stmt:error-too-many-outputs/disp32
21846 $check-mu-get-stmt:end:
21847     # . restore registers
21848     5f/pop-to-edi
21849     5e/pop-to-esi
21850     5b/pop-to-ebx
21851     5a/pop-to-edx
21852     59/pop-to-ecx
21853     58/pop-to-eax
21854     # . epilogue
21855     89/<- %esp 5/r32/ebp
21856     5d/pop-to-ebp
21857     c3/return
21858 
21859 $check-mu-get-stmt:error-too-few-inouts:
21860     (write-buffered *(ebp+0x10) "fn ")
21861     8b/-> *(ebp+0xc) 0/r32/eax
21862     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21863     (write-buffered *(ebp+0x10) %eax)
21864     (write-buffered *(ebp+0x10) ": stmt get: too few inouts (2 required)\n")
21865     (flush *(ebp+0x10))
21866     (stop *(ebp+0x14) 1)
21867     # never gets here
21868 
21869 $check-mu-get-stmt:error-too-many-inouts:
21870     (write-buffered *(ebp+0x10) "fn ")
21871     8b/-> *(ebp+0xc) 0/r32/eax
21872     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21873     (write-buffered *(ebp+0x10) %eax)
21874     (write-buffered *(ebp+0x10) ": stmt get: too many inouts (2 required)\n")
21875     (flush *(ebp+0x10))
21876     (stop *(ebp+0x14) 1)
21877     # never gets here
21878 
21879 $check-mu-get-stmt:error-too-few-outputs:
21880     (write-buffered *(ebp+0x10) "fn ")
21881     8b/-> *(ebp+0xc) 0/r32/eax
21882     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21883     (write-buffered *(ebp+0x10) %eax)
21884     (write-buffered *(ebp+0x10) ": stmt get: must have an output\n")
21885     (flush *(ebp+0x10))
21886     (stop *(ebp+0x14) 1)
21887     # never gets here
21888 
21889 $check-mu-get-stmt:error-too-many-outputs:
21890     (write-buffered *(ebp+0x10) "fn ")
21891     8b/-> *(ebp+0xc) 0/r32/eax
21892     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21893     (write-buffered *(ebp+0x10) %eax)
21894     (write-buffered *(ebp+0x10) ": stmt get: too many outputs (1 required)\n")
21895     (flush *(ebp+0x10))
21896     (stop *(ebp+0x14) 1)
21897     # never gets here
21898 
21899 $check-mu-get-stmt:error-bad-base:
21900     # error("fn " fn ": stmt get: var '" base->name "' must have a 'type' definition\n")
21901     (write-buffered *(ebp+0x10) "fn ")
21902     8b/-> *(ebp+0xc) 0/r32/eax
21903     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21904     (write-buffered *(ebp+0x10) %eax)
21905     (write-buffered *(ebp+0x10) ": stmt get: var '")
21906     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21907     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
21908     (lookup *eax *(eax+4))  # Var-name Var-name => eax
21909     (write-buffered *(ebp+0x10) %eax)
21910     (write-buffered *(ebp+0x10) "' must have a 'type' definition\n")
21911     (flush *(ebp+0x10))
21912     (stop *(ebp+0x14) 1)
21913     # never gets here
21914 
21915 $check-mu-get-stmt:error-base-type-addr-but-not-register:
21916     (write-buffered *(ebp+0x10) "fn ")
21917     8b/-> *(ebp+0xc) 0/r32/eax
21918     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21919     (write-buffered *(ebp+0x10) %eax)
21920     (write-buffered *(ebp+0x10) ": stmt get: var '")
21921     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
21922     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
21923     (lookup *eax *(eax+4))  # Var-name Var-name => eax
21924     (write-buffered *(ebp+0x10) %eax)
21925     (write-buffered *(ebp+0x10) "' is an 'addr' type, and so must live in a register\n")
21926     (flush *(ebp+0x10))
21927     (stop *(ebp+0x14) 1)
21928     # never gets here
21929 
21930 $check-mu-get-stmt:error-bad-field:
21931     # error("fn " fn ": stmt get: type " type " has no member called '" curr->name "'\n")
21932     (write-buffered *(ebp+0x10) "fn ")
21933     8b/-> *(ebp+0xc) 0/r32/eax
21934     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21935     (write-buffered *(ebp+0x10) %eax)
21936     (write-buffered *(ebp+0x10) ": stmt get: type '")
21937     # . write(Type-id->data[tmp])
21938     bf/copy-to-edi Type-id/imm32
21939     8b/-> *(edi+ebx<<2+0xc) 6/r32/esi
21940     {
21941       81 7/subop/compare %esi 0/imm32
21942       74/jump-if-= break/disp8
21943       (write-buffered *(ebp+0x10) %esi)
21944     }
21945     # .
21946     (write-buffered *(ebp+0x10) "' has no member called '")
21947     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
21948     (write-buffered *(ebp+0x10) %eax)
21949     (write-buffered *(ebp+0x10) "'\n")
21950     (flush *(ebp+0x10))
21951     (stop *(ebp+0x14) 1)
21952     # never gets here
21953 
21954 $check-mu-get-stmt:error-output-not-in-register:
21955     (write-buffered *(ebp+0x10) "fn ")
21956     8b/-> *(ebp+0xc) 0/r32/eax
21957     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21958     (write-buffered *(ebp+0x10) %eax)
21959     (write-buffered *(ebp+0x10) ": stmt get: output '")
21960     (lookup *edi *(edi+4))  # Var-name Var-name => eax
21961     (write-buffered *(ebp+0x10) %eax)
21962     (write-buffered *(ebp+0x10) "' is not in a register\n")
21963     (flush *(ebp+0x10))
21964     (stop *(ebp+0x14) 1)
21965     # never gets here
21966 
21967 $check-mu-get-stmt:error-output-type-not-address:
21968     (write-buffered *(ebp+0x10) "fn ")
21969     8b/-> *(ebp+0xc) 0/r32/eax
21970     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21971     (write-buffered *(ebp+0x10) %eax)
21972     (write-buffered *(ebp+0x10) ": stmt get: output must be an addr\n")
21973     (flush *(ebp+0x10))
21974     (stop *(ebp+0x14) 1)
21975     # never gets here
21976 
21977 $check-mu-get-stmt:error-bad-output-type:
21978     (write-buffered *(ebp+0x10) "fn ")
21979     8b/-> *(ebp+0xc) 0/r32/eax
21980     (lookup *eax *(eax+4))  # Function-name Function-name => eax
21981     (write-buffered *(ebp+0x10) %eax)
21982     (write-buffered *(ebp+0x10) ": stmt get: wrong output type for member '")
21983     (write-buffered *(ebp+0x10) %ecx)
21984     (write-buffered *(ebp+0x10) "' of type '")
21985     bf/copy-to-edi Type-id/imm32
21986     8b/-> *(edi+ebx<<2+0xc) 6/r32/esi
21987     {
21988       81 7/subop/compare %esi 0/imm32
21989       74/jump-if-= break/disp8
21990       (write-buffered *(ebp+0x10) %esi)
21991     }
21992     (write-buffered *(ebp+0x10) "'\n")
21993     (flush *(ebp+0x10))
21994     (stop *(ebp+0x14) 1)
21995     # never gets here
21996 
21997 check-mu-index-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
21998     # . prologue
21999     55/push-ebp
22000     89/<- %ebp 4/r32/esp
22001     # . save registers
22002     50/push-eax
22003     51/push-ecx
22004     52/push-edx
22005     53/push-ebx
22006     56/push-esi
22007     57/push-edi
22008     # esi = stmt
22009     8b/-> *(ebp+8) 6/r32/esi
22010     # - check for 0 inouts
22011     # var base/ecx: (addr var) = stmt->inouts->value
22012     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22013 $check-mu-index-stmt:check-no-inouts:
22014     3d/compare-eax-and 0/imm32
22015     0f 84/jump-if-= $check-mu-index-stmt:error-too-few-inouts/disp32
22016     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
22017     89/<- %ecx 0/r32/eax
22018     # - check base type is either (addr array ...) in register or (array ...) on stack
22019     # var base-type/ebx: (addr type-tree) = lookup(base->type)
22020     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
22021     89/<- %ebx 0/r32/eax
22022     # if base-type is an atom, abort with a precise error
22023     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
22024     {
22025       74/jump-if-= break/disp8
22026       (is-simple-mu-type? %ebx 3)  # array => eax
22027       3d/compare-eax-and 0/imm32/false
22028       0f 85/jump-if-!= $check-mu-index-stmt:error-base-array-atom-type/disp32
22029       0f 84/jump-if-= $check-mu-index-stmt:error-base-non-array-type/disp32
22030     }
22031 $check-mu-index-stmt:base-is-compound:
22032     # if type->left not addr or array, abort
22033     {
22034       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
22035       (is-simple-mu-type? %eax 2)  # addr => eax
22036       3d/compare-eax-and 0/imm32/false
22037       75/jump-if-!= break/disp8
22038       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
22039       (is-simple-mu-type? %eax 3)  # array => eax
22040       3d/compare-eax-and 0/imm32/false
22041       75/jump-if-!= break/disp8
22042       e9/jump $check-mu-index-stmt:error-base-non-array-type/disp32
22043     }
22044     # if (type->left == addr) ensure type->right->left == array and type->register exists
22045     {
22046       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
22047       (is-simple-mu-type? %eax 2)  # addr => eax
22048       3d/compare-eax-and 0/imm32/false
22049       74/jump-if-= break/disp8
22050 $check-mu-index-stmt:base-is-addr:
22051       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
22052       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
22053       (is-simple-mu-type? %eax 3)  # array => eax
22054       3d/compare-eax-and 0/imm32/false
22055       0f 84/jump-if-= $check-mu-index-stmt:error-base-non-array-type/disp32
22056 $check-mu-index-stmt:check-base-addr-is-register:
22057       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
22058       0f 84/jump-if-= $check-mu-index-stmt:error-base-address-array-type-on-stack/disp32
22059     }
22060     # if (type->left == array) ensure type->register doesn't exist
22061     {
22062       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
22063       (is-simple-mu-type? %eax 3)  # array => eax
22064       3d/compare-eax-and 0/imm32/false
22065       74/jump-if-= break/disp8
22066 $check-mu-index-stmt:base-is-array:
22067       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
22068       0f 85/jump-if-!= $check-mu-index-stmt:error-base-array-type-in-register/disp32
22069     }
22070     # if (base-type->left == addr) base-type = base-type->right
22071     {
22072       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
22073       (is-simple-mu-type? %eax 2)  # addr => eax
22074       3d/compare-eax-and 0/imm32/false
22075       74/jump-if-= break/disp8
22076       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
22077       89/<- %ebx 0/r32/eax
22078     }
22079     # - check for 1 inout
22080     # var index/ecx: (addr stmt-var) = stmt->inouts->next->value
22081     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22082     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
22083 $check-mu-index-stmt:check-single-inout:
22084     3d/compare-eax-and 0/imm32
22085     0f 84/jump-if-= $check-mu-index-stmt:error-too-few-inouts/disp32
22086     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
22087     89/<- %ecx 0/r32/eax
22088     # - check index is either a literal or register
22089     # var index-type/edx: (addr type-tree)
22090     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
22091     89/<- %edx 0/r32/eax
22092     # if index type is an atom, it must be a literal or int
22093     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
22094     {
22095       74/jump-if-= break/disp8
22096 $check-mu-index-stmt:index-type-is-atom:
22097       (is-simple-mu-type? %edx 0)  # literal => eax
22098       3d/compare-eax-and 0/imm32/false
22099       75/jump-if-!= $check-mu-index-stmt:index-type-done/disp8
22100       (is-simple-mu-type? %edx 1)  # int => eax
22101       3d/compare-eax-and 0/imm32/false
22102       75/jump-if-!= $check-mu-index-stmt:index-type-done/disp8
22103       (is-simple-mu-type? %edx 7)  # offset => eax
22104       3d/compare-eax-and 0/imm32/false
22105       0f 85/jump-if-!= $check-mu-index-stmt:error-index-offset-atom-type/disp32
22106       e9/jump $check-mu-index-stmt:error-invalid-index-type/disp32
22107     }
22108     # if index type is a non-atom: it must be an offset
22109     {
22110       75/jump-if-!= break/disp8
22111 $check-mu-index-stmt:index-type-is-non-atom:
22112       (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
22113       (is-simple-mu-type? %eax 7)  # offset => eax
22114       3d/compare-eax-and 0/imm32/false
22115       0f 84/jump-if-= $check-mu-index-stmt:error-invalid-index-type/disp32
22116     }
22117 $check-mu-index-stmt:index-type-done:
22118     # check index is either a literal or in a register
22119     {
22120       (is-simple-mu-type? %edx 0)  # literal => eax
22121       3d/compare-eax-and 0/imm32/false
22122       75/jump-if-!= break/disp8
22123 $check-mu-index-stmt:check-index-in-register:
22124       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
22125       0f 84/jump-if-= $check-mu-index-stmt:error-index-on-stack/disp32
22126     }
22127     # - if index is an 'int', check that element type of base has size 1, 2, 4 or 8 bytes.
22128     {
22129       (is-simple-mu-type? %edx 1)  # int => eax
22130       3d/compare-eax-and 0/imm32/false
22131       74/jump-if-= break/disp8
22132 $check-mu-index-stmt:check-index-can-be-int:
22133       (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22134       (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
22135       (array-element-size %eax)  # => eax
22136       3d/compare-eax-and 1/imm32
22137       74/jump-if-= break/disp8
22138       3d/compare-eax-and 2/imm32
22139       74/jump-if-= break/disp8
22140       3d/compare-eax-and 4/imm32
22141       74/jump-if-= break/disp8
22142       3d/compare-eax-and 8/imm32
22143       74/jump-if-= break/disp8
22144       e9/jump $check-mu-index-stmt:error-index-needs-offset/disp32
22145     }
22146     # - check for too many inouts
22147     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22148     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
22149     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
22150     3d/compare-eax-and 0/imm32/false
22151     0f 85/jump-if-!= $check-mu-index-stmt:error-too-many-inouts/disp32
22152     # - check for 0 outputs
22153     # var output/edi: (addr var) = stmt->outputs->value
22154     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
22155     3d/compare-eax-and 0/imm32/false
22156     0f 84/jump-if-= $check-mu-index-stmt:error-too-few-outputs/disp32
22157     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
22158     89/<- %edi 0/r32/eax
22159     # - check output type
22160     # must have a non-atomic type
22161     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
22162     89/<- %edx 0/r32/eax
22163     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
22164     0f 85/jump-if-!= $check-mu-index-stmt:error-output-type-not-address/disp32
22165     # type must start with (addr ...)
22166     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
22167     (is-simple-mu-type? %eax 2)  # addr => eax
22168     3d/compare-eax-and 0/imm32/false
22169     0f 84/jump-if-= $check-mu-index-stmt:error-output-type-not-address/disp32
22170     # if tail(base-type) != tail(output-type) abort
22171     (type-tail %ebx)  # => eax
22172     89/<- %ebx 0/r32/eax
22173     (type-tail %edx)  # => eax
22174     (type-equal? %ebx %eax)  # => eax
22175     3d/compare-eax-and 0/imm32/false
22176     0f 84/jump-if-= $check-mu-index-stmt:error-bad-output-type/disp32
22177     # - check for too many outputs
22178     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
22179     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
22180     3d/compare-eax-and 0/imm32/false
22181     0f 85/jump-if-!= $check-mu-index-stmt:error-too-many-outputs/disp32
22182 $check-mu-index-stmt:end:
22183     # . restore registers
22184     5f/pop-to-edi
22185     5e/pop-to-esi
22186     5b/pop-to-ebx
22187     5a/pop-to-edx
22188     59/pop-to-ecx
22189     58/pop-to-eax
22190     # . epilogue
22191     89/<- %esp 5/r32/ebp
22192     5d/pop-to-ebp
22193     c3/return
22194 
22195 $check-mu-index-stmt:error-base-non-array-type:
22196     (write-buffered *(ebp+0x10) "fn ")
22197     8b/-> *(ebp+0xc) 0/r32/eax
22198     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22199     (write-buffered *(ebp+0x10) %eax)
22200     (write-buffered *(ebp+0x10) ": stmt index: var '")
22201     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22202     (write-buffered *(ebp+0x10) %eax)
22203     (write-buffered *(ebp+0x10) "' is not an array\n")
22204     (flush *(ebp+0x10))
22205     (stop *(ebp+0x14) 1)
22206     # never gets here
22207 
22208 $check-mu-index-stmt:error-base-array-atom-type:
22209     (write-buffered *(ebp+0x10) "fn ")
22210     8b/-> *(ebp+0xc) 0/r32/eax
22211     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22212     (write-buffered *(ebp+0x10) %eax)
22213     (write-buffered *(ebp+0x10) ": stmt index: array '")
22214     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22215     (write-buffered *(ebp+0x10) %eax)
22216     (write-buffered *(ebp+0x10) "' must specify the type of its elements\n")
22217     (flush *(ebp+0x10))
22218     (stop *(ebp+0x14) 1)
22219     # never gets here
22220 
22221 $check-mu-index-stmt:error-base-address-array-type-on-stack:
22222     (write-buffered *(ebp+0x10) "fn ")
22223     8b/-> *(ebp+0xc) 0/r32/eax
22224     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22225     (write-buffered *(ebp+0x10) %eax)
22226     (write-buffered *(ebp+0x10) ": stmt index: var '")
22227     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22228     (write-buffered *(ebp+0x10) %eax)
22229     (write-buffered *(ebp+0x10) "' is an addr to an array, and so must live in a register\n")
22230     (flush *(ebp+0x10))
22231     (stop *(ebp+0x14) 1)
22232     # never gets here
22233 
22234 $check-mu-index-stmt:error-base-array-type-in-register:
22235     (write-buffered *(ebp+0x10) "fn ")
22236     8b/-> *(ebp+0xc) 0/r32/eax
22237     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22238     (write-buffered *(ebp+0x10) %eax)
22239     (write-buffered *(ebp+0x10) ": stmt index: var '")
22240     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22241     (write-buffered *(ebp+0x10) %eax)
22242     (write-buffered *(ebp+0x10) "' is an array, and so must live on the stack\n")
22243     (flush *(ebp+0x10))
22244     (stop *(ebp+0x14) 1)
22245     # never gets here
22246 
22247 $check-mu-index-stmt:error-too-few-inouts:
22248     (write-buffered *(ebp+0x10) "fn ")
22249     8b/-> *(ebp+0xc) 0/r32/eax
22250     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22251     (write-buffered *(ebp+0x10) %eax)
22252     (write-buffered *(ebp+0x10) ": stmt index: too few inouts (2 required)\n")
22253     (flush *(ebp+0x10))
22254     (stop *(ebp+0x14) 1)
22255     # never gets here
22256 
22257 $check-mu-index-stmt:error-invalid-index-type:
22258     (write-buffered *(ebp+0x10) "fn ")
22259     8b/-> *(ebp+0xc) 0/r32/eax
22260     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22261     (write-buffered *(ebp+0x10) %eax)
22262     (write-buffered *(ebp+0x10) ": stmt index: second argument '")
22263     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22264     (write-buffered *(ebp+0x10) %eax)
22265     (write-buffered *(ebp+0x10) "' must be an int or offset\n")
22266     (flush *(ebp+0x10))
22267     (stop *(ebp+0x14) 1)
22268     # never gets here
22269 
22270 $check-mu-index-stmt:error-index-offset-atom-type:
22271     (write-buffered *(ebp+0x10) "fn ")
22272     8b/-> *(ebp+0xc) 0/r32/eax
22273     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22274     (write-buffered *(ebp+0x10) %eax)
22275     (write-buffered *(ebp+0x10) ": stmt index: offset '")
22276     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22277     (write-buffered *(ebp+0x10) %eax)
22278     (write-buffered *(ebp+0x10) "' must specify the type of array elements\n")
22279     (flush *(ebp+0x10))
22280     (stop *(ebp+0x14) 1)
22281     # never gets here
22282 
22283 $check-mu-index-stmt:error-index-on-stack:
22284     (write-buffered *(ebp+0x10) "fn ")
22285     8b/-> *(ebp+0xc) 0/r32/eax
22286     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22287     (write-buffered *(ebp+0x10) %eax)
22288     (write-buffered *(ebp+0x10) ": stmt index: second argument '")
22289     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22290     (write-buffered *(ebp+0x10) %eax)
22291     (write-buffered *(ebp+0x10) "' must be in a register\n")
22292     (flush *(ebp+0x10))
22293     (stop *(ebp+0x14) 1)
22294     # never gets here
22295 
22296 $check-mu-index-stmt:error-index-needs-offset:
22297     (write-buffered *(ebp+0x10) "fn ")
22298     8b/-> *(ebp+0xc) 0/r32/eax
22299     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22300     (write-buffered *(ebp+0x10) %eax)
22301     (write-buffered *(ebp+0x10) ": stmt index: cannot take an int for array '")
22302     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22303     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
22304     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22305     (write-buffered *(ebp+0x10) %eax)
22306     (write-buffered *(ebp+0x10) "'; create an offset instead. See mu.md for details.\n")
22307     (flush *(ebp+0x10))
22308     (stop *(ebp+0x14) 1)
22309     # never gets here
22310 
22311 $check-mu-index-stmt:error-too-many-inouts:
22312     (write-buffered *(ebp+0x10) "fn ")
22313     8b/-> *(ebp+0xc) 0/r32/eax
22314     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22315     (write-buffered *(ebp+0x10) %eax)
22316     (write-buffered *(ebp+0x10) ": stmt index: too many inouts (2 required)\n")
22317     (flush *(ebp+0x10))
22318     (stop *(ebp+0x14) 1)
22319     # never gets here
22320 
22321 $check-mu-index-stmt:error-too-few-outputs:
22322     (write-buffered *(ebp+0x10) "fn ")
22323     8b/-> *(ebp+0xc) 0/r32/eax
22324     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22325     (write-buffered *(ebp+0x10) %eax)
22326     (write-buffered *(ebp+0x10) ": stmt index: must have an output\n")
22327     (flush *(ebp+0x10))
22328     (stop *(ebp+0x14) 1)
22329     # never gets here
22330 
22331 $check-mu-index-stmt:error-too-many-outputs:
22332     (write-buffered *(ebp+0x10) "fn ")
22333     8b/-> *(ebp+0xc) 0/r32/eax
22334     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22335     (write-buffered *(ebp+0x10) %eax)
22336     (write-buffered *(ebp+0x10) ": stmt index: too many outputs (1 required)\n")
22337     (flush *(ebp+0x10))
22338     (stop *(ebp+0x14) 1)
22339     # never gets here
22340 
22341 $check-mu-index-stmt:error-output-not-in-register:
22342     (write-buffered *(ebp+0x10) "fn ")
22343     8b/-> *(ebp+0xc) 0/r32/eax
22344     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22345     (write-buffered *(ebp+0x10) %eax)
22346     (write-buffered *(ebp+0x10) ": stmt index: output '")
22347     (lookup *edi *(edi+4))  # Var-name Var-name => eax
22348     (write-buffered *(ebp+0x10) %eax)
22349     (write-buffered *(ebp+0x10) "' is not in a register\n")
22350     (flush *(ebp+0x10))
22351     (stop *(ebp+0x14) 1)
22352     # never gets here
22353 
22354 $check-mu-index-stmt:error-output-type-not-address:
22355     (write-buffered *(ebp+0x10) "fn ")
22356     8b/-> *(ebp+0xc) 0/r32/eax
22357     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22358     (write-buffered *(ebp+0x10) %eax)
22359     (write-buffered *(ebp+0x10) ": stmt index: output '")
22360     (lookup *edi *(edi+4))  # Var-name Var-name => eax
22361     (write-buffered *(ebp+0x10) %eax)
22362     (write-buffered *(ebp+0x10) "' must be an addr\n")
22363     (flush *(ebp+0x10))
22364     (stop *(ebp+0x14) 1)
22365     # never gets here
22366 
22367 $check-mu-index-stmt:error-bad-output-type:
22368     (write-buffered *(ebp+0x10) "fn ")
22369     8b/-> *(ebp+0xc) 0/r32/eax
22370     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22371     (write-buffered *(ebp+0x10) %eax)
22372     (write-buffered *(ebp+0x10) ": stmt index: output '")
22373     (lookup *edi *(edi+4))  # Var-name Var-name => eax
22374     (write-buffered *(ebp+0x10) %eax)
22375     (write-buffered *(ebp+0x10) "' does not have the right type\n")
22376     (flush *(ebp+0x10))
22377     (stop *(ebp+0x14) 1)
22378     # never gets here
22379 
22380 check-mu-length-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
22381     # . prologue
22382     55/push-ebp
22383     89/<- %ebp 4/r32/esp
22384     # . save registers
22385     50/push-eax
22386     51/push-ecx
22387     52/push-edx
22388     53/push-ebx
22389     56/push-esi
22390     57/push-edi
22391     # esi = stmt
22392     8b/-> *(ebp+8) 6/r32/esi
22393     # - check for 0 inouts
22394     # var base/ecx: (addr var) = stmt->inouts->value
22395     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22396 $check-mu-length-stmt:check-no-inouts:
22397     3d/compare-eax-and 0/imm32
22398     0f 84/jump-if-= $check-mu-length-stmt:error-too-few-inouts/disp32
22399     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
22400     89/<- %ecx 0/r32/eax
22401     # - check base type is either (addr array ...) in register or (array ...) on stack
22402     # var base-type/ebx: (addr type-tree) = lookup(base->type)
22403     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
22404     89/<- %ebx 0/r32/eax
22405     # if base-type is an atom, abort with a precise error
22406     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
22407     {
22408       74/jump-if-= break/disp8
22409       (is-simple-mu-type? %ebx 3)  # array => eax
22410       3d/compare-eax-and 0/imm32/false
22411       0f 85/jump-if-!= $check-mu-length-stmt:error-base-array-atom-type/disp32
22412       0f 84/jump-if-= $check-mu-length-stmt:error-base-non-array-type/disp32
22413     }
22414 $check-mu-length-stmt:base-is-compound:
22415     # if type->left not addr or array, abort
22416     {
22417       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
22418       (is-simple-mu-type? %eax 2)  # addr => eax
22419       3d/compare-eax-and 0/imm32/false
22420       75/jump-if-!= break/disp8
22421       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
22422       (is-simple-mu-type? %eax 3)  # array => eax
22423       3d/compare-eax-and 0/imm32/false
22424       75/jump-if-!= break/disp8
22425       e9/jump $check-mu-length-stmt:error-base-non-array-type/disp32
22426     }
22427     # if (type->left == addr) ensure type->right->left == array and type->register exists
22428     {
22429       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
22430       (is-simple-mu-type? %eax 2)  # addr => eax
22431       3d/compare-eax-and 0/imm32/false
22432       74/jump-if-= break/disp8
22433 $check-mu-length-stmt:base-is-addr:
22434       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
22435       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
22436       (is-simple-mu-type? %eax 3)  # array => eax
22437       3d/compare-eax-and 0/imm32/false
22438       0f 84/jump-if-= $check-mu-length-stmt:error-base-non-array-type/disp32
22439 $check-mu-length-stmt:check-base-addr-is-register:
22440       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
22441       0f 84/jump-if-= $check-mu-length-stmt:error-base-address-array-type-on-stack/disp32
22442     }
22443     # if (type->left == array) ensure type->register doesn't exist
22444     {
22445       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
22446       (is-simple-mu-type? %eax 3)  # array => eax
22447       3d/compare-eax-and 0/imm32/false
22448       74/jump-if-= break/disp8
22449 $check-mu-length-stmt:base-is-array:
22450       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
22451       0f 85/jump-if-!= $check-mu-length-stmt:error-base-array-type-in-register/disp32
22452     }
22453     # if (base-type->left == addr) base-type = base-type->right
22454     {
22455       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
22456       (is-simple-mu-type? %eax 2)  # addr => eax
22457       3d/compare-eax-and 0/imm32/false
22458       74/jump-if-= break/disp8
22459       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
22460       89/<- %ebx 0/r32/eax
22461     }
22462     # - check for too many inouts
22463     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22464     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
22465     3d/compare-eax-and 0/imm32/false
22466     0f 85/jump-if-!= $check-mu-length-stmt:error-too-many-inouts/disp32
22467     # - check for 0 outputs
22468     # var output/edi: (addr var) = stmt->outputs->value
22469     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
22470     3d/compare-eax-and 0/imm32/false
22471     0f 84/jump-if-= $check-mu-length-stmt:error-too-few-outputs/disp32
22472     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
22473     89/<- %edi 0/r32/eax
22474     # - check output type
22475     # must have a non-atomic type
22476     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
22477     (is-simple-mu-type? %eax 1)  # int => eax
22478     3d/compare-eax-and 0/imm32/false
22479     0f 84/jump-if-= $check-mu-length-stmt:error-invalid-output-type/disp32
22480     # - check for too many outputs
22481     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
22482     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
22483     3d/compare-eax-and 0/imm32/false
22484     0f 85/jump-if-!= $check-mu-length-stmt:error-too-many-outputs/disp32
22485 $check-mu-length-stmt:end:
22486     # . restore registers
22487     5f/pop-to-edi
22488     5e/pop-to-esi
22489     5b/pop-to-ebx
22490     5a/pop-to-edx
22491     59/pop-to-ecx
22492     58/pop-to-eax
22493     # . epilogue
22494     89/<- %esp 5/r32/ebp
22495     5d/pop-to-ebp
22496     c3/return
22497 
22498 $check-mu-length-stmt:error-base-non-array-type:
22499     (write-buffered *(ebp+0x10) "fn ")
22500     8b/-> *(ebp+0xc) 0/r32/eax
22501     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22502     (write-buffered *(ebp+0x10) %eax)
22503     (write-buffered *(ebp+0x10) ": stmt length: var '")
22504     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22505     (write-buffered *(ebp+0x10) %eax)
22506     (write-buffered *(ebp+0x10) "' is not an array\n")
22507     (flush *(ebp+0x10))
22508     (stop *(ebp+0x14) 1)
22509     # never gets here
22510 
22511 $check-mu-length-stmt:error-base-array-atom-type:
22512     (write-buffered *(ebp+0x10) "fn ")
22513     8b/-> *(ebp+0xc) 0/r32/eax
22514     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22515     (write-buffered *(ebp+0x10) %eax)
22516     (write-buffered *(ebp+0x10) ": stmt length: array '")
22517     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22518     (write-buffered *(ebp+0x10) %eax)
22519     (write-buffered *(ebp+0x10) "' must specify the type of its elements\n")
22520     (flush *(ebp+0x10))
22521     (stop *(ebp+0x14) 1)
22522     # never gets here
22523 
22524 $check-mu-length-stmt:error-base-address-array-type-on-stack:
22525     (write-buffered *(ebp+0x10) "fn ")
22526     8b/-> *(ebp+0xc) 0/r32/eax
22527     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22528     (write-buffered *(ebp+0x10) %eax)
22529     (write-buffered *(ebp+0x10) ": stmt length: var '")
22530     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22531     (write-buffered *(ebp+0x10) %eax)
22532     (write-buffered *(ebp+0x10) "' is an addr to an array, and so must live in a register\n")
22533     (flush *(ebp+0x10))
22534     (stop *(ebp+0x14) 1)
22535     # never gets here
22536 
22537 $check-mu-length-stmt:error-base-array-type-in-register:
22538     (write-buffered *(ebp+0x10) "fn ")
22539     8b/-> *(ebp+0xc) 0/r32/eax
22540     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22541     (write-buffered *(ebp+0x10) %eax)
22542     (write-buffered *(ebp+0x10) ": stmt length: var '")
22543     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22544     (write-buffered *(ebp+0x10) %eax)
22545     (write-buffered *(ebp+0x10) "' is an array, and so must live on the stack\n")
22546     (flush *(ebp+0x10))
22547     (stop *(ebp+0x14) 1)
22548     # never gets here
22549 
22550 $check-mu-length-stmt:error-too-few-inouts:
22551     (write-buffered *(ebp+0x10) "fn ")
22552     8b/-> *(ebp+0xc) 0/r32/eax
22553     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22554     (write-buffered *(ebp+0x10) %eax)
22555     (write-buffered *(ebp+0x10) ": stmt length: too few inouts (1 required)\n")
22556     (flush *(ebp+0x10))
22557     (stop *(ebp+0x14) 1)
22558     # never gets here
22559 
22560 $check-mu-length-stmt:error-invalid-index-type:
22561     (write-buffered *(ebp+0x10) "fn ")
22562     8b/-> *(ebp+0xc) 0/r32/eax
22563     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22564     (write-buffered *(ebp+0x10) %eax)
22565     (write-buffered *(ebp+0x10) ": stmt length: second argument '")
22566     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22567     (write-buffered *(ebp+0x10) %eax)
22568     (write-buffered *(ebp+0x10) "' must be an int or offset\n")
22569     (flush *(ebp+0x10))
22570     (stop *(ebp+0x14) 1)
22571     # never gets here
22572 
22573 $check-mu-length-stmt:error-index-offset-atom-type:
22574     (write-buffered *(ebp+0x10) "fn ")
22575     8b/-> *(ebp+0xc) 0/r32/eax
22576     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22577     (write-buffered *(ebp+0x10) %eax)
22578     (write-buffered *(ebp+0x10) ": stmt length: offset '")
22579     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22580     (write-buffered *(ebp+0x10) %eax)
22581     (write-buffered *(ebp+0x10) "' must specify the type of array elements\n")
22582     (flush *(ebp+0x10))
22583     (stop *(ebp+0x14) 1)
22584     # never gets here
22585 
22586 $check-mu-length-stmt:error-index-on-stack:
22587     (write-buffered *(ebp+0x10) "fn ")
22588     8b/-> *(ebp+0xc) 0/r32/eax
22589     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22590     (write-buffered *(ebp+0x10) %eax)
22591     (write-buffered *(ebp+0x10) ": stmt length: second argument '")
22592     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22593     (write-buffered *(ebp+0x10) %eax)
22594     (write-buffered *(ebp+0x10) "' must be in a register\n")
22595     (flush *(ebp+0x10))
22596     (stop *(ebp+0x14) 1)
22597     # never gets here
22598 
22599 $check-mu-length-stmt:error-index-needs-offset:
22600     (write-buffered *(ebp+0x10) "fn ")
22601     8b/-> *(ebp+0xc) 0/r32/eax
22602     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22603     (write-buffered *(ebp+0x10) %eax)
22604     (write-buffered *(ebp+0x10) ": stmt length: cannot take an int for array '")
22605     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22606     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
22607     (lookup *eax *(eax+4))  # Var-name Var-name => eax
22608     (write-buffered *(ebp+0x10) %eax)
22609     (write-buffered *(ebp+0x10) "'; create an offset instead. See mu.md for details.\n")
22610     (flush *(ebp+0x10))
22611     (stop *(ebp+0x14) 1)
22612     # never gets here
22613 
22614 $check-mu-length-stmt:error-too-many-inouts:
22615     (write-buffered *(ebp+0x10) "fn ")
22616     8b/-> *(ebp+0xc) 0/r32/eax
22617     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22618     (write-buffered *(ebp+0x10) %eax)
22619     (write-buffered *(ebp+0x10) ": stmt length: too many inouts (1 required)\n")
22620     (flush *(ebp+0x10))
22621     (stop *(ebp+0x14) 1)
22622     # never gets here
22623 
22624 $check-mu-length-stmt:error-too-few-outputs:
22625     (write-buffered *(ebp+0x10) "fn ")
22626     8b/-> *(ebp+0xc) 0/r32/eax
22627     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22628     (write-buffered *(ebp+0x10) %eax)
22629     (write-buffered *(ebp+0x10) ": stmt length: must have an output\n")
22630     (flush *(ebp+0x10))
22631     (stop *(ebp+0x14) 1)
22632     # never gets here
22633 
22634 $check-mu-length-stmt:error-too-many-outputs:
22635     (write-buffered *(ebp+0x10) "fn ")
22636     8b/-> *(ebp+0xc) 0/r32/eax
22637     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22638     (write-buffered *(ebp+0x10) %eax)
22639     (write-buffered *(ebp+0x10) ": stmt length: too many outputs (1 required)\n")
22640     (flush *(ebp+0x10))
22641     (stop *(ebp+0x14) 1)
22642     # never gets here
22643 
22644 $check-mu-length-stmt:error-output-not-in-register:
22645     (write-buffered *(ebp+0x10) "fn ")
22646     8b/-> *(ebp+0xc) 0/r32/eax
22647     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22648     (write-buffered *(ebp+0x10) %eax)
22649     (write-buffered *(ebp+0x10) ": stmt length: output '")
22650     (lookup *edi *(edi+4))  # Var-name Var-name => eax
22651     (write-buffered *(ebp+0x10) %eax)
22652     (write-buffered *(ebp+0x10) "' is not in a register\n")
22653     (flush *(ebp+0x10))
22654     (stop *(ebp+0x14) 1)
22655     # never gets here
22656 
22657 $check-mu-length-stmt:error-invalid-output-type:
22658     (write-buffered *(ebp+0x10) "fn ")
22659     8b/-> *(ebp+0xc) 0/r32/eax
22660     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22661     (write-buffered *(ebp+0x10) %eax)
22662     (write-buffered *(ebp+0x10) ": stmt length: output '")
22663     (lookup *edi *(edi+4))  # Var-name Var-name => eax
22664     (write-buffered *(ebp+0x10) %eax)
22665     (write-buffered *(ebp+0x10) "' does not have the right type\n")
22666     (flush *(ebp+0x10))
22667     (stop *(ebp+0x14) 1)
22668     # never gets here
22669 
22670 check-mu-compute-offset-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
22671     # . prologue
22672     55/push-ebp
22673     89/<- %ebp 4/r32/esp
22674     # . save registers
22675     50/push-eax
22676     51/push-ecx
22677     52/push-edx
22678     53/push-ebx
22679     56/push-esi
22680     57/push-edi
22681     # esi = stmt
22682     8b/-> *(ebp+8) 6/r32/esi
22683     # - check for 0 inouts
22684     # var base/ecx: (addr var) = stmt->inouts->value
22685     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22686 $check-mu-compute-offset-stmt:check-no-inouts:
22687     3d/compare-eax-and 0/imm32
22688     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-too-few-inouts/disp32
22689     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
22690     89/<- %ecx 0/r32/eax
22691     # - check base type is either (addr array ...) in register or (array ...) on stack
22692     # var base-type/ebx: (addr type-tree) = lookup(base->type)
22693     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
22694     89/<- %ebx 0/r32/eax
22695     # if base-type is an atom, abort with a precise error
22696     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
22697     {
22698       74/jump-if-= break/disp8
22699       (is-simple-mu-type? %ebx 3)  # array => eax
22700       3d/compare-eax-and 0/imm32/false
22701       0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-base-array-atom-type/disp32
22702       0f 84/jump-if-= $check-mu-compute-offset-stmt:error-base-non-array-type/disp32
22703     }
22704 $check-mu-compute-offset-stmt:base-is-compound:
22705     # if type->left not addr or array, abort
22706     {
22707       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
22708       (is-simple-mu-type? %eax 2)  # addr => eax
22709       3d/compare-eax-and 0/imm32/false
22710       75/jump-if-!= break/disp8
22711       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
22712       (is-simple-mu-type? %eax 3)  # array => eax
22713       3d/compare-eax-and 0/imm32/false
22714       75/jump-if-!= break/disp8
22715       e9/jump $check-mu-compute-offset-stmt:error-base-non-array-type/disp32
22716     }
22717     # if (type->left == addr) ensure type->right->left == array and type->register exists
22718     {
22719       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
22720       (is-simple-mu-type? %eax 2)  # addr => eax
22721       3d/compare-eax-and 0/imm32/false
22722       74/jump-if-= break/disp8
22723 $check-mu-compute-offset-stmt:base-is-addr:
22724       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
22725       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
22726       (is-simple-mu-type? %eax 3)  # array => eax
22727       3d/compare-eax-and 0/imm32/false
22728       0f 84/jump-if-= $check-mu-compute-offset-stmt:error-base-non-array-type/disp32
22729     }
22730     # if (base-type->left == addr) base-type = base-type->right
22731     {
22732       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
22733       (is-simple-mu-type? %eax 2)  # addr => eax
22734       3d/compare-eax-and 0/imm32/false
22735       74/jump-if-= break/disp8
22736       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
22737       89/<- %ebx 0/r32/eax
22738     }
22739     # - check for 1 inout
22740     # var index/ecx: (addr stmt-var) = stmt->inouts->next->value
22741     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22742     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
22743 $check-mu-compute-offset-stmt:check-single-inout:
22744     3d/compare-eax-and 0/imm32
22745     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-too-few-inouts/disp32
22746     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
22747     89/<- %ecx 0/r32/eax
22748     # - check index is either a literal or register
22749     # var index-type/edx: (addr type-tree)
22750     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
22751     89/<- %edx 0/r32/eax
22752     # index type must be a literal or int
22753     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
22754     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-invalid-index-type/disp32
22755     {
22756 $check-mu-compute-offset-stmt:index-type-is-atom:
22757       (is-simple-mu-type? %edx 0)  # literal => eax
22758       3d/compare-eax-and 0/imm32/false
22759       75/jump-if-!= break/disp8
22760       (is-simple-mu-type? %edx 1)  # int => eax
22761       3d/compare-eax-and 0/imm32/false
22762       75/jump-if-!= break/disp8
22763       e9/jump $check-mu-compute-offset-stmt:error-invalid-index-type/disp32
22764     }
22765     # - check for too many inouts
22766     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22767     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
22768     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
22769     3d/compare-eax-and 0/imm32/false
22770     0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-too-many-inouts/disp32
22771     # - check for 0 outputs
22772     # var output/edi: (addr var) = stmt->outputs->value
22773     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
22774     3d/compare-eax-and 0/imm32/false
22775     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-too-few-outputs/disp32
22776     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
22777     89/<- %edi 0/r32/eax
22778     # - check output type
22779     # must have a non-atomic type
22780     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
22781     89/<- %edx 0/r32/eax
22782     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
22783     0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-output-type-not-offset/disp32
22784     # type must start with (offset ...)
22785     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
22786     (is-simple-mu-type? %eax 7)  # offset => eax
22787     3d/compare-eax-and 0/imm32/false
22788     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-output-type-not-offset/disp32
22789     # if tail(base-type) != tail(output-type) abort
22790     (type-tail %ebx)  # => eax
22791     89/<- %ebx 0/r32/eax
22792     (type-tail %edx)  # => eax
22793     (type-equal? %ebx %eax)  # => eax
22794     3d/compare-eax-and 0/imm32/false
22795     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-bad-output-type/disp32
22796     # - check for too many outputs
22797     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
22798     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
22799     3d/compare-eax-and 0/imm32/false
22800     0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-too-many-outputs/disp32
22801 $check-mu-compute-offset-stmt:end:
22802     # . restore registers
22803     5f/pop-to-edi
22804     5e/pop-to-esi
22805     5b/pop-to-ebx
22806     5a/pop-to-edx
22807     59/pop-to-ecx
22808     58/pop-to-eax
22809     # . epilogue
22810     89/<- %esp 5/r32/ebp
22811     5d/pop-to-ebp
22812     c3/return
22813 
22814 $check-mu-compute-offset-stmt:error-base-non-array-type:
22815     (write-buffered *(ebp+0x10) "fn ")
22816     8b/-> *(ebp+0xc) 0/r32/eax
22817     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22818     (write-buffered *(ebp+0x10) %eax)
22819     (write-buffered *(ebp+0x10) ": stmt compute-offset: var '")
22820     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22821     (write-buffered *(ebp+0x10) %eax)
22822     (write-buffered *(ebp+0x10) "' is not an array\n")
22823     (flush *(ebp+0x10))
22824     (stop *(ebp+0x14) 1)
22825     # never gets here
22826 
22827 $check-mu-compute-offset-stmt:error-base-array-atom-type:
22828     (write-buffered *(ebp+0x10) "fn ")
22829     8b/-> *(ebp+0xc) 0/r32/eax
22830     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22831     (write-buffered *(ebp+0x10) %eax)
22832     (write-buffered *(ebp+0x10) ": stmt compute-offset: array '")
22833     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22834     (write-buffered *(ebp+0x10) %eax)
22835     (write-buffered *(ebp+0x10) "' must specify the type of its elements\n")
22836     (flush *(ebp+0x10))
22837     (stop *(ebp+0x14) 1)
22838     # never gets here
22839 
22840 $check-mu-compute-offset-stmt:error-too-few-inouts:
22841     (write-buffered *(ebp+0x10) "fn ")
22842     8b/-> *(ebp+0xc) 0/r32/eax
22843     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22844     (write-buffered *(ebp+0x10) %eax)
22845     (write-buffered *(ebp+0x10) ": stmt compute-offset: too few inouts (2 required)\n")
22846     (flush *(ebp+0x10))
22847     (stop *(ebp+0x14) 1)
22848     # never gets here
22849 
22850 $check-mu-compute-offset-stmt:error-invalid-index-type:
22851     (write-buffered *(ebp+0x10) "fn ")
22852     8b/-> *(ebp+0xc) 0/r32/eax
22853     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22854     (write-buffered *(ebp+0x10) %eax)
22855     (write-buffered *(ebp+0x10) ": stmt compute-offset: second argument '")
22856     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22857     (write-buffered *(ebp+0x10) %eax)
22858     (write-buffered *(ebp+0x10) "' must be an int\n")
22859     (flush *(ebp+0x10))
22860     (stop *(ebp+0x14) 1)
22861     # never gets here
22862 
22863 $check-mu-compute-offset-stmt:error-index-offset-atom-type:
22864     (write-buffered *(ebp+0x10) "fn ")
22865     8b/-> *(ebp+0xc) 0/r32/eax
22866     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22867     (write-buffered *(ebp+0x10) %eax)
22868     (write-buffered *(ebp+0x10) ": stmt compute-offset: offset '")
22869     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22870     (write-buffered *(ebp+0x10) %eax)
22871     (write-buffered *(ebp+0x10) "' must specify the type of array elements\n")
22872     (flush *(ebp+0x10))
22873     (stop *(ebp+0x14) 1)
22874     # never gets here
22875 
22876 $check-mu-compute-offset-stmt:error-index-on-stack:
22877     (write-buffered *(ebp+0x10) "fn ")
22878     8b/-> *(ebp+0xc) 0/r32/eax
22879     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22880     (write-buffered *(ebp+0x10) %eax)
22881     (write-buffered *(ebp+0x10) ": stmt compute-offset: second argument '")
22882     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
22883     (write-buffered *(ebp+0x10) %eax)
22884     (write-buffered *(ebp+0x10) "' must be in a register\n")
22885     (flush *(ebp+0x10))
22886     (stop *(ebp+0x14) 1)
22887     # never gets here
22888 
22889 $check-mu-compute-offset-stmt:error-too-many-inouts:
22890     (write-buffered *(ebp+0x10) "fn ")
22891     8b/-> *(ebp+0xc) 0/r32/eax
22892     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22893     (write-buffered *(ebp+0x10) %eax)
22894     (write-buffered *(ebp+0x10) ": stmt compute-offset: too many inouts (2 required)\n")
22895     (flush *(ebp+0x10))
22896     (stop *(ebp+0x14) 1)
22897     # never gets here
22898 
22899 $check-mu-compute-offset-stmt:error-too-few-outputs:
22900     (write-buffered *(ebp+0x10) "fn ")
22901     8b/-> *(ebp+0xc) 0/r32/eax
22902     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22903     (write-buffered *(ebp+0x10) %eax)
22904     (write-buffered *(ebp+0x10) ": stmt compute-offset: must have an output\n")
22905     (flush *(ebp+0x10))
22906     (stop *(ebp+0x14) 1)
22907     # never gets here
22908 
22909 $check-mu-compute-offset-stmt:error-too-many-outputs:
22910     (write-buffered *(ebp+0x10) "fn ")
22911     8b/-> *(ebp+0xc) 0/r32/eax
22912     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22913     (write-buffered *(ebp+0x10) %eax)
22914     (write-buffered *(ebp+0x10) ": stmt compute-offset: too many outputs (1 required)\n")
22915     (flush *(ebp+0x10))
22916     (stop *(ebp+0x14) 1)
22917     # never gets here
22918 
22919 $check-mu-compute-offset-stmt:error-output-not-in-register:
22920     (write-buffered *(ebp+0x10) "fn ")
22921     8b/-> *(ebp+0xc) 0/r32/eax
22922     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22923     (write-buffered *(ebp+0x10) %eax)
22924     (write-buffered *(ebp+0x10) ": stmt compute-offset: output '")
22925     (lookup *edi *(edi+4))  # Var-name Var-name => eax
22926     (write-buffered *(ebp+0x10) %eax)
22927     (write-buffered *(ebp+0x10) "' is not in a register\n")
22928     (flush *(ebp+0x10))
22929     (stop *(ebp+0x14) 1)
22930     # never gets here
22931 
22932 $check-mu-compute-offset-stmt:error-output-type-not-offset:
22933     (write-buffered *(ebp+0x10) "fn ")
22934     8b/-> *(ebp+0xc) 0/r32/eax
22935     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22936     (write-buffered *(ebp+0x10) %eax)
22937     (write-buffered *(ebp+0x10) ": stmt compute-offset: output '")
22938     (lookup *edi *(edi+4))  # Var-name Var-name => eax
22939     (write-buffered *(ebp+0x10) %eax)
22940     (write-buffered *(ebp+0x10) "' must be an offset\n")
22941     (flush *(ebp+0x10))
22942     (stop *(ebp+0x14) 1)
22943     # never gets here
22944 
22945 $check-mu-compute-offset-stmt:error-bad-output-type:
22946     (write-buffered *(ebp+0x10) "fn ")
22947     8b/-> *(ebp+0xc) 0/r32/eax
22948     (lookup *eax *(eax+4))  # Function-name Function-name => eax
22949     (write-buffered *(ebp+0x10) %eax)
22950     (write-buffered *(ebp+0x10) ": stmt compute-offset: output '")
22951     (lookup *edi *(edi+4))  # Var-name Var-name => eax
22952     (write-buffered *(ebp+0x10) %eax)
22953     (write-buffered *(ebp+0x10) "' does not have the right type\n")
22954     (flush *(ebp+0x10))
22955     (stop *(ebp+0x14) 1)
22956     # never gets here
22957 
22958 check-mu-copy-object-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
22959     # . prologue
22960     55/push-ebp
22961     89/<- %ebp 4/r32/esp
22962     # . save registers
22963     50/push-eax
22964     51/push-ecx
22965     53/push-ebx
22966     56/push-esi
22967     57/push-edi
22968     # esi = stmt
22969     8b/-> *(ebp+8) 6/r32/esi
22970 $check-mu-copy-object-stmt:check-for-output:
22971     # if stmt->outputs abort
22972     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
22973     3d/compare-eax-and 0/imm32
22974     0f 85/jump-if-!= $check-mu-copy-object-stmt:error-too-many-outputs/disp32
22975 $check-mu-copy-object-stmt:get-left:
22976     # var dest/edi: (addr stmt-var) = stmt->inouts
22977     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
22978     89/<- %edi 0/r32/eax
22979     # zero inouts
22980     3d/compare-eax-and 0/imm32
22981     0f 84/jump-if-= $check-mu-copy-object-stmt:error-incorrect-inouts/disp32
22982 $check-mu-copy-object-stmt:get-src:
22983     # var src/esi: (addr stmt-var) = dest->next
22984     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
22985     89/<- %esi 0/r32/eax
22986     # 1 inout
22987     3d/compare-eax-and 0/imm32
22988     0f 84/jump-if-= $check-mu-copy-object-stmt:error-incorrect-inouts/disp32
22989     # > 2 inouts
22990     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
22991     3d/compare-eax-and 0/imm32
22992     0f 85/jump-if-!= $check-mu-copy-object-stmt:error-incorrect-inouts/disp32
22993 $check-mu-copy-object-stmt:types:
22994     # var src-type/ecx: (addr type-tree) = src->value->type
22995     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
22996     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
22997     89/<- %ecx 0/r32/eax
22998     # if (src->is-deref?) src-type = src-type->payload
22999     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
23000     3d/compare-eax-and 0/imm32/false
23001     {
23002       74/jump-if-= break/disp8
23003       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
23004       # if src-type->right is null, src-type = src-type->left
23005       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
23006       {
23007         75/jump-if-!= break/disp8
23008         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23009       }
23010       89/<- %ecx 0/r32/eax
23011     }
23012     # if src-type is not addr, abort
23013     (is-mu-addr-type? %ecx)  # => eax
23014     3d/compare-eax-and 0/imm32/false
23015     0f 84/jump-if-= $check-mu-copy-object-stmt:error-invalid-types/disp32
23016     # var dest-type/ebx: (addr type-tree) = dest->value->type
23017     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
23018     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
23019     89/<- %ebx 0/r32/eax
23020     # if (dest->is-deref?) dest-type = dest-type->payload
23021     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
23022     3d/compare-eax-and 0/imm32/false
23023     {
23024       74/jump-if-= break/disp8
23025       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
23026       # if dest-type->right is null, dest-type = dest-type->left
23027       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
23028       {
23029         75/jump-if-!= break/disp8
23030         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23031       }
23032       89/<- %ebx 0/r32/eax
23033     }
23034     # if (dest-type != src-type) abort
23035     (type-equal? %ecx %ebx)  # => eax
23036     3d/compare-eax-and 0/imm32
23037     0f 84/jump-if-= $check-mu-copy-object-stmt:error-invalid-types/disp32
23038 $check-mu-copy-object-stmt:end:
23039     # . restore registers
23040     5f/pop-to-edi
23041     5e/pop-to-esi
23042     5b/pop-to-ebx
23043     59/pop-to-ecx
23044     58/pop-to-eax
23045     # . epilogue
23046     89/<- %esp 5/r32/ebp
23047     5d/pop-to-ebp
23048     c3/return
23049 
23050 $check-mu-copy-object-stmt:error-incorrect-inouts:
23051     (write-buffered *(ebp+0x10) "fn ")
23052     8b/-> *(ebp+0xc) 0/r32/eax
23053     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23054     (write-buffered *(ebp+0x10) %eax)
23055     (write-buffered *(ebp+0x10) ": stmt 'copy-object' must have two inouts\n")
23056     (flush *(ebp+0x10))
23057     (stop *(ebp+0x14) 1)
23058     # never gets here
23059 
23060 $check-mu-copy-object-stmt:error-too-many-outputs:
23061     (write-buffered *(ebp+0x10) "fn ")
23062     8b/-> *(ebp+0xc) 0/r32/eax
23063     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23064     (write-buffered *(ebp+0x10) %eax)
23065     (write-buffered *(ebp+0x10) ": stmt 'copy-object' must not have any outputs\n")
23066     (flush *(ebp+0x10))
23067     (stop *(ebp+0x14) 1)
23068     # never gets here
23069 
23070 $check-mu-copy-object-stmt:error-invalid-types:
23071     (write-buffered *(ebp+0x10) "fn ")
23072     8b/-> *(ebp+0xc) 0/r32/eax
23073     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23074     (write-buffered *(ebp+0x10) %eax)
23075     (write-buffered *(ebp+0x10) ": stmt copy-object: two inouts with identical addr types expected\n")
23076     (flush *(ebp+0x10))
23077     (stop *(ebp+0x14) 1)
23078     # never gets here
23079 
23080 check-mu-clear-object-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
23081     # . prologue
23082     55/push-ebp
23083     89/<- %ebp 4/r32/esp
23084     # . save registers
23085     50/push-eax
23086     51/push-ecx
23087     53/push-ebx
23088     56/push-esi
23089     57/push-edi
23090     # esi = stmt
23091     8b/-> *(ebp+8) 6/r32/esi
23092 $check-mu-clear-object-stmt:check-for-output:
23093     # if stmt->outputs abort
23094     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
23095     3d/compare-eax-and 0/imm32
23096     0f 85/jump-if-!= $check-mu-clear-object-stmt:error-too-many-outputs/disp32
23097 $check-mu-clear-object-stmt:get-left:
23098     # var dest/edi: (addr stmt-var) = stmt->inouts
23099     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23100     89/<- %edi 0/r32/eax
23101     # zero inouts
23102     3d/compare-eax-and 0/imm32
23103     0f 84/jump-if-= $check-mu-clear-object-stmt:error-incorrect-inouts/disp32
23104 $check-mu-clear-object-stmt:get-src:
23105     # > 1 inout
23106     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
23107     3d/compare-eax-and 0/imm32
23108     0f 85/jump-if-!= $check-mu-clear-object-stmt:error-incorrect-inouts/disp32
23109 $check-mu-clear-object-stmt:types:
23110     # var src-type/ecx: (addr type-tree) = src->value->type
23111     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
23112     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
23113     89/<- %ecx 0/r32/eax
23114     # if (src->is-deref?) src-type = src-type->payload
23115     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
23116     3d/compare-eax-and 0/imm32/false
23117     {
23118       74/jump-if-= break/disp8
23119       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
23120       # if src-type->right is null, src-type = src-type->left
23121       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
23122       {
23123         75/jump-if-!= break/disp8
23124         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23125       }
23126       89/<- %ecx 0/r32/eax
23127     }
23128     # if src-type is not addr, abort
23129     (is-mu-addr-type? %ecx)  # => eax
23130     3d/compare-eax-and 0/imm32/false
23131     0f 84/jump-if-= $check-mu-clear-object-stmt:error-invalid-type/disp32
23132 $check-mu-clear-object-stmt:end:
23133     # . restore registers
23134     5f/pop-to-edi
23135     5e/pop-to-esi
23136     5b/pop-to-ebx
23137     59/pop-to-ecx
23138     58/pop-to-eax
23139     # . epilogue
23140     89/<- %esp 5/r32/ebp
23141     5d/pop-to-ebp
23142     c3/return
23143 
23144 $check-mu-clear-object-stmt:error-incorrect-inouts:
23145     (write-buffered *(ebp+0x10) "fn ")
23146     8b/-> *(ebp+0xc) 0/r32/eax
23147     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23148     (write-buffered *(ebp+0x10) %eax)
23149     (write-buffered *(ebp+0x10) ": stmt 'clear-object' must have a single inout\n")
23150     (flush *(ebp+0x10))
23151     (stop *(ebp+0x14) 1)
23152     # never gets here
23153 
23154 $check-mu-clear-object-stmt:error-too-many-outputs:
23155     (write-buffered *(ebp+0x10) "fn ")
23156     8b/-> *(ebp+0xc) 0/r32/eax
23157     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23158     (write-buffered *(ebp+0x10) %eax)
23159     (write-buffered *(ebp+0x10) ": stmt 'clear-object' must not have any outputs\n")
23160     (flush *(ebp+0x10))
23161     (stop *(ebp+0x14) 1)
23162     # never gets here
23163 
23164 $check-mu-clear-object-stmt:error-invalid-type:
23165     (write-buffered *(ebp+0x10) "fn ")
23166     8b/-> *(ebp+0xc) 0/r32/eax
23167     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23168     (write-buffered *(ebp+0x10) %eax)
23169     (write-buffered *(ebp+0x10) ": stmt clear-object: inout must have an addr type\n")
23170     (flush *(ebp+0x10))
23171     (stop *(ebp+0x14) 1)
23172     # never gets here
23173 
23174 check-mu-allocate-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
23175     # . prologue
23176     55/push-ebp
23177     89/<- %ebp 4/r32/esp
23178     # . save registers
23179     50/push-eax
23180     53/push-ebx
23181     56/push-esi
23182     57/push-edi
23183     # esi = stmt
23184     8b/-> *(ebp+8) 6/r32/esi
23185 $check-mu-allocate-stmt:check-for-output:
23186     # if stmt->outputs abort
23187     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
23188     3d/compare-eax-and 0/imm32
23189     0f 85/jump-if-!= $check-mu-allocate-stmt:error-too-many-outputs/disp32
23190 $check-mu-allocate-stmt:get-target:
23191     # var target/edi: (addr stmt-var) = stmt->inouts
23192     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23193     89/<- %edi 0/r32/eax
23194     # zero inouts
23195     3d/compare-eax-and 0/imm32
23196     0f 84/jump-if-= $check-mu-allocate-stmt:error-incorrect-inouts/disp32
23197     # > 1 inouts
23198     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
23199     3d/compare-eax-and 0/imm32
23200     0f 85/jump-if-!= $check-mu-allocate-stmt:error-incorrect-inouts/disp32
23201 $check-mu-allocate-stmt:check-type:
23202     # var target-type/ebx: (addr type-tree) = target->value->type
23203     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
23204     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
23205     89/<- %ebx 0/r32/eax
23206     # if (target->is-deref?) target-type = target-type->payload
23207     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
23208     3d/compare-eax-and 0/imm32/false
23209     {
23210       74/jump-if-= break/disp8
23211       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
23212       # if target-type->right is null, target-type = target-type->left
23213       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
23214       {
23215         75/jump-if-!= break/disp8
23216         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23217       }
23218       89/<- %ebx 0/r32/eax
23219     }
23220     # if target-type is not addr, abort
23221     (is-mu-addr-type? %ebx)  # => eax
23222     3d/compare-eax-and 0/imm32/false
23223     0f 84/jump-if-= $check-mu-allocate-stmt:error-invalid-type/disp32
23224     # if target-type->right is an atom, abort
23225     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
23226     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
23227     0f 85/jump-if-!= $check-mu-allocate-stmt:error-invalid-type/disp32
23228     # if target-type->right->left is not handle, abort
23229     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23230     (is-simple-mu-type? %eax 4)  # handle => eax
23231     3d/compare-eax-and 0/imm32/false
23232     0f 84/jump-if-= $check-mu-allocate-stmt:error-invalid-type/disp32
23233 $check-mu-allocate-stmt:end:
23234     # . restore registers
23235     5f/pop-to-edi
23236     5e/pop-to-esi
23237     5b/pop-to-ebx
23238     58/pop-to-eax
23239     # . epilogue
23240     89/<- %esp 5/r32/ebp
23241     5d/pop-to-ebp
23242     c3/return
23243 
23244 $check-mu-allocate-stmt:error-incorrect-inouts:
23245     (write-buffered *(ebp+0x10) "fn ")
23246     8b/-> *(ebp+0xc) 0/r32/eax
23247     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23248     (write-buffered *(ebp+0x10) %eax)
23249     (write-buffered *(ebp+0x10) ": stmt 'allocate' must have a single inout\n")
23250     (flush *(ebp+0x10))
23251     (stop *(ebp+0x14) 1)
23252     # never gets here
23253 
23254 $check-mu-allocate-stmt:error-too-many-outputs:
23255     (write-buffered *(ebp+0x10) "fn ")
23256     8b/-> *(ebp+0xc) 0/r32/eax
23257     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23258     (write-buffered *(ebp+0x10) %eax)
23259     (write-buffered *(ebp+0x10) ": stmt 'allocate' must not have any outputs\n")
23260     (flush *(ebp+0x10))
23261     (stop *(ebp+0x14) 1)
23262     # never gets here
23263 
23264 $check-mu-allocate-stmt:error-invalid-type:
23265     (write-buffered *(ebp+0x10) "fn ")
23266     8b/-> *(ebp+0xc) 0/r32/eax
23267     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23268     (write-buffered *(ebp+0x10) %eax)
23269     (write-buffered *(ebp+0x10) ": stmt allocate: inout '")
23270     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
23271     (lookup *eax *(eax+4))  # Var-name Var-name => eax
23272     (write-buffered *(ebp+0x10) %eax)
23273     (write-buffered *(ebp+0x10) "' must have type (addr handle ...)\n")
23274     (flush *(ebp+0x10))
23275     (stop *(ebp+0x14) 1)
23276     # never gets here
23277 
23278 check-mu-populate-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
23279     # . prologue
23280     55/push-ebp
23281     89/<- %ebp 4/r32/esp
23282     # . save registers
23283     50/push-eax
23284     53/push-ebx
23285     56/push-esi
23286     57/push-edi
23287     # esi = stmt
23288     8b/-> *(ebp+8) 6/r32/esi
23289 $check-mu-populate-stmt:check-for-output:
23290     # if stmt->outputs abort
23291     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
23292     3d/compare-eax-and 0/imm32
23293     0f 85/jump-if-!= $check-mu-populate-stmt:error-too-many-outputs/disp32
23294 $check-mu-populate-stmt:get-target:
23295     # var target/edi: (addr stmt-var) = stmt->inouts
23296     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23297     89/<- %edi 0/r32/eax
23298     # zero inouts
23299     3d/compare-eax-and 0/imm32
23300     0f 84/jump-if-= $check-mu-populate-stmt:error-incorrect-inouts/disp32
23301 $check-mu-populate-stmt:get-length:
23302     # var length/esi: (addr stmt-var) = dest->next
23303     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
23304     89/<- %esi 0/r32/eax
23305     # 1 inout
23306     3d/compare-eax-and 0/imm32
23307     0f 84/jump-if-= $check-mu-populate-stmt:error-incorrect-inouts/disp32
23308     # > 2 inouts
23309     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
23310     3d/compare-eax-and 0/imm32
23311     0f 85/jump-if-!= $check-mu-populate-stmt:error-incorrect-inouts/disp32
23312 $check-mu-populate-stmt:check-target-type:
23313     # var target-type/ebx: (addr type-tree) = target->value->type
23314     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
23315     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
23316     89/<- %ebx 0/r32/eax
23317 $check-mu-populate-stmt:check-target-type-deref:
23318     # if (target->is-deref?) target-type = target-type->payload
23319     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
23320     3d/compare-eax-and 0/imm32/false
23321     {
23322       74/jump-if-= break/disp8
23323       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
23324       # if target-type->right is null, target-type = target-type->left
23325       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
23326       {
23327         75/jump-if-!= break/disp8
23328         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23329       }
23330       89/<- %ebx 0/r32/eax
23331     }
23332 $check-mu-populate-stmt:check-target-type-addr:
23333     # if target-type is not addr, abort
23334     (is-mu-addr-type? %ebx)  # => eax
23335     3d/compare-eax-and 0/imm32/false
23336     0f 84/jump-if-= $check-mu-populate-stmt:error-invalid-target-type/disp32
23337     # if target-type->right is an atom, abort
23338     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
23339     89/<- %ebx 0/r32/eax
23340     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
23341     0f 85/jump-if-!= $check-mu-populate-stmt:error-invalid-target-type/disp32
23342 $check-mu-populate-stmt:check-target-type-handle:
23343     # if target-type->right->left is not handle, abort
23344     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
23345     (is-simple-mu-type? %eax 4)  # handle => eax
23346     3d/compare-eax-and 0/imm32/false
23347     0f 84/jump-if-= $check-mu-populate-stmt:error-invalid-target-type/disp32
23348     # if target-type->right->right is an atom, abort
23349     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
23350     89/<- %ebx 0/r32/eax
23351     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
23352     0f 85/jump-if-!= $check-mu-populate-stmt:error-invalid-target-type/disp32
23353 $check-mu-populate-stmt:check-target-type-array:
23354     # if target-type->right->right->left is not array, abort
23355     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
23356     (is-simple-mu-type? %eax 3)  # array => eax
23357     3d/compare-eax-and 0/imm32/false
23358     0f 84/jump-if-= $check-mu-populate-stmt:error-invalid-target-type/disp32
23359 $check-mu-populate-stmt:check-length-type:
23360     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
23361     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
23362     89/<- %ebx 0/r32/eax
23363     (is-simple-mu-type? %ebx 0)  # literal => eax
23364     3d/compare-eax-and 0/imm32/false
23365     75/jump-if-!= $check-mu-populate-stmt:end/disp8
23366     (is-simple-mu-type? %ebx 1)  # int => eax
23367     3d/compare-eax-and 0/imm32/false
23368     0f 84/jump-if-= $check-mu-populate-stmt:error-invalid-length-type/disp32
23369 $check-mu-populate-stmt:end:
23370     # . restore registers
23371     5f/pop-to-edi
23372     5e/pop-to-esi
23373     5b/pop-to-ebx
23374     58/pop-to-eax
23375     # . epilogue
23376     89/<- %esp 5/r32/ebp
23377     5d/pop-to-ebp
23378     c3/return
23379 
23380 $check-mu-populate-stmt:error-incorrect-inouts:
23381     (write-buffered *(ebp+0x10) "fn ")
23382     8b/-> *(ebp+0xc) 0/r32/eax
23383     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23384     (write-buffered *(ebp+0x10) %eax)
23385     (write-buffered *(ebp+0x10) ": stmt 'populate' must have two inouts\n")
23386     (flush *(ebp+0x10))
23387     (stop *(ebp+0x14) 1)
23388     # never gets here
23389 
23390 $check-mu-populate-stmt:error-too-many-outputs:
23391     (write-buffered *(ebp+0x10) "fn ")
23392     8b/-> *(ebp+0xc) 0/r32/eax
23393     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23394     (write-buffered *(ebp+0x10) %eax)
23395     (write-buffered *(ebp+0x10) ": stmt 'populate' must not have any outputs\n")
23396     (flush *(ebp+0x10))
23397     (stop *(ebp+0x14) 1)
23398     # never gets here
23399 
23400 $check-mu-populate-stmt:error-invalid-target-type:
23401     (write-buffered *(ebp+0x10) "fn ")
23402     8b/-> *(ebp+0xc) 0/r32/eax
23403     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23404     (write-buffered *(ebp+0x10) %eax)
23405     (write-buffered *(ebp+0x10) ": stmt populate: first inout '")
23406     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
23407     (lookup *eax *(eax+4))  # Var-name Var-name => eax
23408     (write-buffered *(ebp+0x10) %eax)
23409     (write-buffered *(ebp+0x10) "' must have type (addr handle array ...)\n")
23410     (flush *(ebp+0x10))
23411     (stop *(ebp+0x14) 1)
23412     # never gets here
23413 
23414 $check-mu-populate-stmt:error-invalid-length-type:
23415     (write-buffered *(ebp+0x10) "fn ")
23416     8b/-> *(ebp+0xc) 0/r32/eax
23417     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23418     (write-buffered *(ebp+0x10) %eax)
23419     (write-buffered *(ebp+0x10) ": stmt populate: second inout '")
23420     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
23421     (lookup *eax *(eax+4))  # Var-name Var-name => eax
23422     (write-buffered *(ebp+0x10) %eax)
23423     (write-buffered *(ebp+0x10) "' must be an int\n")
23424     (flush *(ebp+0x10))
23425     (stop *(ebp+0x14) 1)
23426     # never gets here
23427 
23428 check-mu-populate-stream-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
23429     # . prologue
23430     55/push-ebp
23431     89/<- %ebp 4/r32/esp
23432     # . save registers
23433     50/push-eax
23434     53/push-ebx
23435     56/push-esi
23436     57/push-edi
23437     # esi = stmt
23438     8b/-> *(ebp+8) 6/r32/esi
23439 $check-mu-populate-stream-stmt:check-for-output:
23440     # if stmt->outputs abort
23441     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
23442     3d/compare-eax-and 0/imm32
23443     0f 85/jump-if-!= $check-mu-populate-stream-stmt:error-too-many-outputs/disp32
23444 $check-mu-populate-stream-stmt:get-target:
23445     # var target/edi: (addr stmt-var) = stmt->inouts
23446     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23447     89/<- %edi 0/r32/eax
23448     # zero inouts
23449     3d/compare-eax-and 0/imm32
23450     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-incorrect-inouts/disp32
23451 $check-mu-populate-stream-stmt:get-length:
23452     # var length/esi: (addr stmt-var) = dest->next
23453     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
23454     89/<- %esi 0/r32/eax
23455     # 1 inout
23456     3d/compare-eax-and 0/imm32
23457     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-incorrect-inouts/disp32
23458     # > 2 inouts
23459     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
23460     3d/compare-eax-and 0/imm32
23461     0f 85/jump-if-!= $check-mu-populate-stream-stmt:error-incorrect-inouts/disp32
23462 $check-mu-populate-stream-stmt:check-target-type:
23463     # var target-type/ebx: (addr type-tree) = target->value->type
23464     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
23465     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
23466     89/<- %ebx 0/r32/eax
23467 $check-mu-populate-stream-stmt:check-target-type-deref:
23468     # if (target->is-deref?) target-type = target-type->payload
23469     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
23470     3d/compare-eax-and 0/imm32/false
23471     {
23472       74/jump-if-= break/disp8
23473       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
23474       # if target-type->right is null, target-type = target-type->left
23475       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
23476       {
23477         75/jump-if-!= break/disp8
23478         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23479       }
23480       89/<- %ebx 0/r32/eax
23481     }
23482 $check-mu-populate-stream-stmt:check-target-type-addr:
23483     # if target-type is not addr, abort
23484     (is-mu-addr-type? %ebx)  # => eax
23485     3d/compare-eax-and 0/imm32/false
23486     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
23487     # if target-type->right is an atom, abort
23488     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
23489     89/<- %ebx 0/r32/eax
23490     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
23491     0f 85/jump-if-!= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
23492 $check-mu-populate-stream-stmt:check-target-type-handle:
23493     # if target-type->right->left is not handle, abort
23494     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
23495     (is-simple-mu-type? %eax 4)  # handle => eax
23496     3d/compare-eax-and 0/imm32/false
23497     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
23498     # if target-type->right->right is an atom, abort
23499     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
23500     89/<- %ebx 0/r32/eax
23501     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
23502     0f 85/jump-if-!= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
23503 $check-mu-populate-stream-stmt:check-target-type-stream:
23504     # if target-type->right->right->left is not stream, abort
23505     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
23506     (is-simple-mu-type? %eax 0xb)  # stream => eax
23507     3d/compare-eax-and 0/imm32/false
23508     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
23509 $check-mu-populate-stream-stmt:check-length-type:
23510     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
23511     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
23512     89/<- %ebx 0/r32/eax
23513     (is-simple-mu-type? %ebx 0)  # literal => eax
23514     3d/compare-eax-and 0/imm32/false
23515     75/jump-if-!= $check-mu-populate-stream-stmt:end/disp8
23516     (is-simple-mu-type? %ebx 1)  # int => eax
23517     3d/compare-eax-and 0/imm32/false
23518     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-invalid-length-type/disp32
23519 $check-mu-populate-stream-stmt:end:
23520     # . restore registers
23521     5f/pop-to-edi
23522     5e/pop-to-esi
23523     5b/pop-to-ebx
23524     58/pop-to-eax
23525     # . epilogue
23526     89/<- %esp 5/r32/ebp
23527     5d/pop-to-ebp
23528     c3/return
23529 
23530 $check-mu-populate-stream-stmt:error-incorrect-inouts:
23531     (write-buffered *(ebp+0x10) "fn ")
23532     8b/-> *(ebp+0xc) 0/r32/eax
23533     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23534     (write-buffered *(ebp+0x10) %eax)
23535     (write-buffered *(ebp+0x10) ": stmt 'populate-stream' must have two inouts\n")
23536     (flush *(ebp+0x10))
23537     (stop *(ebp+0x14) 1)
23538     # never gets here
23539 
23540 $check-mu-populate-stream-stmt:error-too-many-outputs:
23541     (write-buffered *(ebp+0x10) "fn ")
23542     8b/-> *(ebp+0xc) 0/r32/eax
23543     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23544     (write-buffered *(ebp+0x10) %eax)
23545     (write-buffered *(ebp+0x10) ": stmt 'populate-stream' must not have any outputs\n")
23546     (flush *(ebp+0x10))
23547     (stop *(ebp+0x14) 1)
23548     # never gets here
23549 
23550 $check-mu-populate-stream-stmt:error-invalid-target-type:
23551     (write-buffered *(ebp+0x10) "fn ")
23552     8b/-> *(ebp+0xc) 0/r32/eax
23553     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23554     (write-buffered *(ebp+0x10) %eax)
23555     (write-buffered *(ebp+0x10) ": stmt populate-stream: first inout '")
23556     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
23557     (lookup *eax *(eax+4))  # Var-name Var-name => eax
23558     (write-buffered *(ebp+0x10) %eax)
23559     (write-buffered *(ebp+0x10) "' must have type (addr handle stream ...)\n")
23560     (flush *(ebp+0x10))
23561     (stop *(ebp+0x14) 1)
23562     # never gets here
23563 
23564 $check-mu-populate-stream-stmt:error-invalid-length-type:
23565     (write-buffered *(ebp+0x10) "fn ")
23566     8b/-> *(ebp+0xc) 0/r32/eax
23567     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23568     (write-buffered *(ebp+0x10) %eax)
23569     (write-buffered *(ebp+0x10) ": stmt populate-stream: second inout '")
23570     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
23571     (lookup *eax *(eax+4))  # Var-name Var-name => eax
23572     (write-buffered *(ebp+0x10) %eax)
23573     (write-buffered *(ebp+0x10) "' must be an int\n")
23574     (flush *(ebp+0x10))
23575     (stop *(ebp+0x14) 1)
23576     # never gets here
23577 
23578 check-mu-read-from-stream-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
23579     # . prologue
23580     55/push-ebp
23581     89/<- %ebp 4/r32/esp
23582     # . save registers
23583     50/push-eax
23584     51/push-ecx
23585     52/push-edx
23586     53/push-ebx
23587     56/push-esi
23588     57/push-edi
23589     # esi = stmt
23590     8b/-> *(ebp+8) 6/r32/esi
23591     # - check for 0 inouts
23592     # var base/ecx: (addr var) = stmt->inouts->value
23593     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23594 $check-mu-read-from-stream-stmt:check-no-inouts:
23595     3d/compare-eax-and 0/imm32
23596     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-too-few-inouts/disp32
23597     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
23598     89/<- %ecx 0/r32/eax
23599     # - check base type is (addr stream T)
23600     # var base-type/ebx: (addr type-tree) = lookup(base->type)
23601     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
23602     89/<- %ebx 0/r32/eax
23603 $check-mu-read-from-stream-stmt:check-base-is-compound:
23604     # if base-type is an atom, abort
23605     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
23606     0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-invalid-base-type/disp32
23607 $check-mu-read-from-stream-stmt:check-base-is-addr:
23608     # if type->left not addr, abort
23609     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
23610     (is-simple-mu-type? %eax 2)  # addr => eax
23611     3d/compare-eax-and 0/imm32/false
23612     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-invalid-base-type/disp32
23613 $check-mu-read-from-stream-stmt:check-base-is-addr-to-stream:
23614     # base-type = base-type->right
23615     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
23616     89/<- %ebx 0/r32/eax
23617     # ensure base-type->left == stream
23618     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23619     (is-simple-mu-type? %eax 0xb)  # stream => eax
23620     3d/compare-eax-and 0/imm32/false
23621     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-invalid-base-type/disp32
23622     # - check target type is (addr T)
23623     # var target/ecx: (addr stmt-var) = stmt->inouts->next->value
23624     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23625     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
23626 $check-mu-read-from-stream-stmt:check-single-inout:
23627     3d/compare-eax-and 0/imm32
23628     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-too-few-inouts/disp32
23629     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
23630     89/<- %ecx 0/r32/eax
23631     # var target-type/edx: (addr type-tree)
23632     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
23633     89/<- %edx 0/r32/eax
23634     # if target-type is an atom, it must be a literal or int
23635 $check-mu-read-from-stream-stmt:check-target-is-compound:
23636     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
23637     0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-target-type-not-address/disp32
23638 $check-mu-read-from-stream-stmt:check-target-type:
23639     # target type must start with (addr ...)
23640     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
23641     (is-simple-mu-type? %eax 2)  # addr => eax
23642     3d/compare-eax-and 0/imm32/false
23643     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-target-type-not-address/disp32
23644     # if tail(base-type) != tail(target-type) abort
23645     (type-tail %ebx)  # => eax
23646     89/<- %ebx 0/r32/eax
23647     (type-tail %edx)  # => eax
23648     (type-equal? %ebx %eax)  # => eax
23649     3d/compare-eax-and 0/imm32/false
23650     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-invalid-target-type/disp32
23651 $check-mu-read-from-stream-stmt:check-too-many-inouts:
23652     # - check for too many inouts
23653     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23654     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
23655     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
23656     3d/compare-eax-and 0/imm32/false
23657     0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-too-many-inouts/disp32
23658 $check-mu-read-from-stream-stmt:check-unexpected-output:
23659     # - check for any output
23660     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
23661     3d/compare-eax-and 0/imm32/false
23662     0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-unexpected-output/disp32
23663 $check-mu-read-from-stream-stmt:end:
23664     # . restore registers
23665     5f/pop-to-edi
23666     5e/pop-to-esi
23667     5b/pop-to-ebx
23668     5a/pop-to-edx
23669     59/pop-to-ecx
23670     58/pop-to-eax
23671     # . epilogue
23672     89/<- %esp 5/r32/ebp
23673     5d/pop-to-ebp
23674     c3/return
23675 
23676 $check-mu-read-from-stream-stmt:error-invalid-base-type:
23677     (write-buffered *(ebp+0x10) "fn ")
23678     8b/-> *(ebp+0xc) 0/r32/eax
23679     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23680     (write-buffered *(ebp+0x10) %eax)
23681     (write-buffered *(ebp+0x10) ": stmt read-from-stream: var '")
23682     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
23683     (write-buffered *(ebp+0x10) %eax)
23684     (write-buffered *(ebp+0x10) "' must be an addr to a stream\n")
23685     (flush *(ebp+0x10))
23686     (stop *(ebp+0x14) 1)
23687     # never gets here
23688 
23689 $check-mu-read-from-stream-stmt:error-too-few-inouts:
23690     (write-buffered *(ebp+0x10) "fn ")
23691     8b/-> *(ebp+0xc) 0/r32/eax
23692     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23693     (write-buffered *(ebp+0x10) %eax)
23694     (write-buffered *(ebp+0x10) ": stmt read-from-stream: too few inouts (2 required)\n")
23695     (flush *(ebp+0x10))
23696     (stop *(ebp+0x14) 1)
23697     # never gets here
23698 
23699 $check-mu-read-from-stream-stmt:error-target-type-not-address:
23700     (write-buffered *(ebp+0x10) "fn ")
23701     8b/-> *(ebp+0xc) 0/r32/eax
23702     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23703     (write-buffered *(ebp+0x10) %eax)
23704     (write-buffered *(ebp+0x10) ": stmt read-from-stream: target '")
23705     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
23706     (write-buffered *(ebp+0x10) %eax)
23707     (write-buffered *(ebp+0x10) "' must be an addr\n")
23708     (flush *(ebp+0x10))
23709     (stop *(ebp+0x14) 1)
23710     # never gets here
23711 
23712 $check-mu-read-from-stream-stmt:error-invalid-target-type:
23713     (write-buffered *(ebp+0x10) "fn ")
23714     8b/-> *(ebp+0xc) 0/r32/eax
23715     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23716     (write-buffered *(ebp+0x10) %eax)
23717     (write-buffered *(ebp+0x10) ": stmt read-from-stream: second inout '")
23718     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
23719     (write-buffered *(ebp+0x10) %eax)
23720     (write-buffered *(ebp+0x10) "' does not have the right type\n")
23721     (flush *(ebp+0x10))
23722     (stop *(ebp+0x14) 1)
23723     # never gets here
23724 
23725 $check-mu-read-from-stream-stmt:error-too-many-inouts:
23726     (write-buffered *(ebp+0x10) "fn ")
23727     8b/-> *(ebp+0xc) 0/r32/eax
23728     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23729     (write-buffered *(ebp+0x10) %eax)
23730     (write-buffered *(ebp+0x10) ": stmt read-from-stream: too many inouts (2 required)\n")
23731     (flush *(ebp+0x10))
23732     (stop *(ebp+0x14) 1)
23733     # never gets here
23734 
23735 $check-mu-read-from-stream-stmt:error-unexpected-output:
23736     (write-buffered *(ebp+0x10) "fn ")
23737     8b/-> *(ebp+0xc) 0/r32/eax
23738     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23739     (write-buffered *(ebp+0x10) %eax)
23740     (write-buffered *(ebp+0x10) ": stmt read-from-stream: unexpected output\n")
23741     (flush *(ebp+0x10))
23742     (stop *(ebp+0x14) 1)
23743     # never gets here
23744 
23745 check-mu-write-to-stream-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
23746     # . prologue
23747     55/push-ebp
23748     89/<- %ebp 4/r32/esp
23749     # . save registers
23750     50/push-eax
23751     51/push-ecx
23752     52/push-edx
23753     53/push-ebx
23754     56/push-esi
23755     57/push-edi
23756     # esi = stmt
23757     8b/-> *(ebp+8) 6/r32/esi
23758     # - check for 0 inouts
23759     # var base/ecx: (addr var) = stmt->inouts->value
23760     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23761 $check-mu-write-to-stream-stmt:check-no-inouts:
23762     3d/compare-eax-and 0/imm32
23763     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-too-few-inouts/disp32
23764     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
23765     89/<- %ecx 0/r32/eax
23766     # - check base type is (addr stream T)
23767     # var base-type/ebx: (addr type-tree) = lookup(base->type)
23768     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
23769     89/<- %ebx 0/r32/eax
23770 $check-mu-write-to-stream-stmt:check-base-is-compound:
23771     # if base-type is an atom, abort
23772     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
23773     0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-invalid-base-type/disp32
23774 $check-mu-write-to-stream-stmt:check-base-is-addr:
23775     # if type->left not addr, abort
23776     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
23777     (is-simple-mu-type? %eax 2)  # addr => eax
23778     3d/compare-eax-and 0/imm32/false
23779     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-invalid-base-type/disp32
23780 $check-mu-write-to-stream-stmt:check-base-is-addr-to-stream:
23781     # base-type = base-type->right
23782     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
23783     89/<- %ebx 0/r32/eax
23784     # ensure base-type->left == stream
23785     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
23786     (is-simple-mu-type? %eax 0xb)  # stream => eax
23787     3d/compare-eax-and 0/imm32/false
23788     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-invalid-base-type/disp32
23789     # - check target type is (addr T)
23790     # var target/ecx: (addr stmt-var) = stmt->inouts->next->value
23791     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23792     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
23793 $check-mu-write-to-stream-stmt:check-single-inout:
23794     3d/compare-eax-and 0/imm32
23795     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-too-few-inouts/disp32
23796     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
23797     89/<- %ecx 0/r32/eax
23798     # var target-type/edx: (addr type-tree)
23799     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
23800     89/<- %edx 0/r32/eax
23801     # if target-type is an atom, it must be a literal or int
23802 $check-mu-write-to-stream-stmt:check-target-is-compound:
23803     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
23804     0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-target-type-not-address/disp32
23805 $check-mu-write-to-stream-stmt:check-target-type:
23806     # target type must start with (addr ...)
23807     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
23808     (is-simple-mu-type? %eax 2)  # addr => eax
23809     3d/compare-eax-and 0/imm32/false
23810     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-target-type-not-address/disp32
23811     # if tail(base-type) != tail(target-type) abort
23812     (type-tail %ebx)  # => eax
23813     89/<- %ebx 0/r32/eax
23814     (type-tail %edx)  # => eax
23815     (type-equal? %ebx %eax)  # => eax
23816     3d/compare-eax-and 0/imm32/false
23817     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-invalid-target-type/disp32
23818 $check-mu-write-to-stream-stmt:check-too-many-inouts:
23819     # - check for too many inouts
23820     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23821     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
23822     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
23823     3d/compare-eax-and 0/imm32/false
23824     0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-too-many-inouts/disp32
23825 $check-mu-write-to-stream-stmt:check-unexpected-output:
23826     # - check for any output
23827     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
23828     3d/compare-eax-and 0/imm32/false
23829     0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-unexpected-output/disp32
23830 $check-mu-write-to-stream-stmt:end:
23831     # . restore registers
23832     5f/pop-to-edi
23833     5e/pop-to-esi
23834     5b/pop-to-ebx
23835     5a/pop-to-edx
23836     59/pop-to-ecx
23837     58/pop-to-eax
23838     # . epilogue
23839     89/<- %esp 5/r32/ebp
23840     5d/pop-to-ebp
23841     c3/return
23842 
23843 $check-mu-write-to-stream-stmt:error-invalid-base-type:
23844     (write-buffered *(ebp+0x10) "fn ")
23845     8b/-> *(ebp+0xc) 0/r32/eax
23846     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23847     (write-buffered *(ebp+0x10) %eax)
23848     (write-buffered *(ebp+0x10) ": stmt write-to-stream: var '")
23849     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
23850     (write-buffered *(ebp+0x10) %eax)
23851     (write-buffered *(ebp+0x10) "' must be an addr to a stream\n")
23852     (flush *(ebp+0x10))
23853     (stop *(ebp+0x14) 1)
23854     # never gets here
23855 
23856 $check-mu-write-to-stream-stmt:error-too-few-inouts:
23857     (write-buffered *(ebp+0x10) "fn ")
23858     8b/-> *(ebp+0xc) 0/r32/eax
23859     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23860     (write-buffered *(ebp+0x10) %eax)
23861     (write-buffered *(ebp+0x10) ": stmt write-to-stream: too few inouts (2 required)\n")
23862     (flush *(ebp+0x10))
23863     (stop *(ebp+0x14) 1)
23864     # never gets here
23865 
23866 $check-mu-write-to-stream-stmt:error-target-type-not-address:
23867     (write-buffered *(ebp+0x10) "fn ")
23868     8b/-> *(ebp+0xc) 0/r32/eax
23869     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23870     (write-buffered *(ebp+0x10) %eax)
23871     (write-buffered *(ebp+0x10) ": stmt write-to-stream: target '")
23872     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
23873     (write-buffered *(ebp+0x10) %eax)
23874     (write-buffered *(ebp+0x10) "' must be an addr\n")
23875     (flush *(ebp+0x10))
23876     (stop *(ebp+0x14) 1)
23877     # never gets here
23878 
23879 $check-mu-write-to-stream-stmt:error-invalid-target-type:
23880     (write-buffered *(ebp+0x10) "fn ")
23881     8b/-> *(ebp+0xc) 0/r32/eax
23882     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23883     (write-buffered *(ebp+0x10) %eax)
23884     (write-buffered *(ebp+0x10) ": stmt write-to-stream: second inout '")
23885     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
23886     (write-buffered *(ebp+0x10) %eax)
23887     (write-buffered *(ebp+0x10) "' does not have the right type\n")
23888     (flush *(ebp+0x10))
23889     (stop *(ebp+0x14) 1)
23890     # never gets here
23891 
23892 $check-mu-write-to-stream-stmt:error-too-many-inouts:
23893     (write-buffered *(ebp+0x10) "fn ")
23894     8b/-> *(ebp+0xc) 0/r32/eax
23895     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23896     (write-buffered *(ebp+0x10) %eax)
23897     (write-buffered *(ebp+0x10) ": stmt write-to-stream: too many inouts (2 required)\n")
23898     (flush *(ebp+0x10))
23899     (stop *(ebp+0x14) 1)
23900     # never gets here
23901 
23902 $check-mu-write-to-stream-stmt:error-unexpected-output:
23903     (write-buffered *(ebp+0x10) "fn ")
23904     8b/-> *(ebp+0xc) 0/r32/eax
23905     (lookup *eax *(eax+4))  # Function-name Function-name => eax
23906     (write-buffered *(ebp+0x10) %eax)
23907     (write-buffered *(ebp+0x10) ": stmt write-to-stream: unexpected output\n")
23908     (flush *(ebp+0x10))
23909     (stop *(ebp+0x14) 1)
23910     # never gets here
23911 
23912 check-mu-convert-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
23913     # . prologue
23914     55/push-ebp
23915     89/<- %ebp 4/r32/esp
23916     # . save registers
23917 $check-mu-convert-stmt:end:
23918     # . restore registers
23919     # . epilogue
23920     89/<- %esp 5/r32/ebp
23921     5d/pop-to-ebp
23922     c3/return
23923 
23924 check-mu-call:  # stmt: (addr stmt), callee: (addr function), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
23925     # . prologue
23926     55/push-ebp
23927     89/<- %ebp 4/r32/esp
23928     # var type-parameters: (addr table (handle array byte) (addr type-tree) 8)
23929     68/push 0/imm32
23930     # var type-parameters-storage: (table (handle array byte) (addr type-tree) 8)
23931     81 5/subop/subtract %esp 0x60/imm32
23932     68/push 0x60/imm32/size
23933     68/push 0/imm32/read
23934     68/push 0/imm32/write
23935     # save a pointer to type-parameters-storage at type-parameters
23936     89/<- *(ebp-4) 4/r32/esp
23937     (clear-stream *(ebp-4))
23938     # . save registers
23939     50/push-eax
23940     51/push-ecx
23941     52/push-edx
23942     53/push-ebx
23943     56/push-esi
23944     57/push-edi
23945     # esi = stmt
23946     8b/-> *(ebp+8) 6/r32/esi
23947     # edi = callee
23948     8b/-> *(ebp+0xc) 7/r32/edi
23949     # var inouts/ecx: (addr stmt-var) = lookup(stmt->inouts)
23950     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
23951     89/<- %ecx 0/r32/eax
23952     # var expected/edx: (addr list var) = lookup(f->inouts)
23953     (lookup *(edi+8) *(edi+0xc))  # Function-inouts Function-inouts => eax
23954     89/<- %edx 0/r32/eax
23955     {
23956 $check-mu-call:check-for-inouts:
23957       # if (inouts == 0) break
23958       81 7/subop/compare %ecx 0/imm32
23959       0f 84/jump-if-= break/disp32
23960       # if (expected == 0) error
23961       81 7/subop/compare %edx 0/imm32
23962       0f 84/jump-if-= break/disp32
23963 $check-mu-call:check-null-addr:
23964       # if (inouts->value->name == "0") continue
23965       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
23966       (lookup *eax *(eax+4))  # Var-name Var-name => eax
23967       (string-equal? %eax "0")  # => eax
23968       3d/compare-eax-and 0/imm32/false
23969       0f 85/jump-if-!= $check-mu-call:continue-to-next-inout/disp32
23970 $check-mu-call:check-inout-type:
23971       # var t/ebx: (addr type-tree) = inouts->value->type
23972       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
23973       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
23974       89/<- %ebx 0/r32/eax
23975       # if (inouts->is-deref?) t = t->right
23976       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
23977       {
23978         74/jump-if-= break/disp8
23979         (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
23980         89/<- %ebx 0/r32/eax
23981         # if t->right is null, t = t->left
23982         81 7/subop/compare *(ebx+0xc) 0/imm32  # Type-tree-right
23983         75/jump-if-!= break/disp8
23984         (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
23985         89/<- %ebx 0/r32/eax
23986       }
23987       # var v2/eax: (addr v) = lookup(expected->value)
23988       (lookup *edx *(edx+4))  # List-value List-value => eax
23989       # var t2/eax: (addr type-tree) = lookup(v2->type)
23990       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
23991       # if (t != t2) error
23992       (type-match? %eax %ebx *(ebp-4))  # => eax
23993       3d/compare-eax-and 0/imm32/false
23994       {
23995         0f 85/jump-if-!= break/disp32
23996         (write-buffered *(ebp+0x14) "fn ")
23997         8b/-> *(ebp+0x10) 0/r32/eax
23998         (lookup *eax *(eax+4))  # Function-name Function-name => eax
23999         (write-buffered *(ebp+0x14) %eax)
24000         (write-buffered *(ebp+0x14) ": call ")
24001         (lookup *edi *(edi+4))  # Function-name Function-name => eax
24002         (write-buffered *(ebp+0x14) %eax)
24003         (write-buffered *(ebp+0x14) ": type for inout '")
24004         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
24005         (lookup *eax *(eax+4))  # Var-name Var-name => eax
24006         (write-buffered *(ebp+0x14) %eax)
24007         (write-buffered *(ebp+0x14) "' is not right\n")
24008         (flush *(ebp+0x14))
24009         (stop *(ebp+0x18) 1)
24010       }
24011 $check-mu-call:continue-to-next-inout:
24012       # inouts = lookup(inouts->next)
24013       (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
24014       89/<- %ecx 0/r32/eax
24015       # expected = lookup(expected->next)
24016       (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
24017       89/<- %edx 0/r32/eax
24018       #
24019       e9/jump loop/disp32
24020     }
24021 $check-mu-call:check-inout-count:
24022     # if (inouts == expected) proceed
24023     39/compare %ecx 2/r32/edx
24024     {
24025       0f 84/jump-if-= break/disp32
24026       # exactly one of the two is null
24027       # if (inouts == 0) error("too many inouts")
24028       {
24029         81 7/subop/compare %ecx 0/imm32
24030         0f 84/jump-if-= break/disp32
24031         (write-buffered *(ebp+0x14) "fn ")
24032         8b/-> *(ebp+0x10) 0/r32/eax
24033         (lookup *eax *(eax+4))  # Function-name Function-name => eax
24034         (write-buffered *(ebp+0x14) %eax)
24035         (write-buffered *(ebp+0x14) ": call ")
24036         (lookup *edi *(edi+4))  # Function-name Function-name => eax
24037         (write-buffered *(ebp+0x14) %eax)
24038         (write-buffered *(ebp+0x14) ": too many inouts\n")
24039         (flush *(ebp+0x14))
24040         (stop *(ebp+0x18) 1)
24041       }
24042       # if (expected == 0) error("too few inouts")
24043       {
24044         81 7/subop/compare %edx 0/imm32
24045         0f 84/jump-if-= break/disp32
24046         (write-buffered *(ebp+0x14) "fn ")
24047         8b/-> *(ebp+0x10) 0/r32/eax
24048         (lookup *eax *(eax+4))  # Function-name Function-name => eax
24049         (write-buffered *(ebp+0x14) %eax)
24050         (write-buffered *(ebp+0x14) ": call ")
24051         (lookup *edi *(edi+4))  # Function-name Function-name => eax
24052         (write-buffered *(ebp+0x14) %eax)
24053         (write-buffered *(ebp+0x14) ": too few inouts\n")
24054         (flush *(ebp+0x14))
24055         (stop *(ebp+0x18) 1)
24056       }
24057     }
24058 $check-mu-call:check-outputs:
24059     # var outputs/ecx: (addr stmt-var) = lookup(stmt->outputs)
24060     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
24061     89/<- %ecx 0/r32/eax
24062     # var expected/edx: (addr list var) = lookup(f->outputs)
24063     (lookup *(edi+0x10) *(edi+0x14))  # Function-outputs Function-outputs => eax
24064     89/<- %edx 0/r32/eax
24065     {
24066 $check-mu-call:check-for-outputs:
24067       # if (outputs == 0) break
24068       81 7/subop/compare %ecx 0/imm32
24069       0f 84/jump-if-= break/disp32
24070       # if (expected == 0) error
24071       81 7/subop/compare %edx 0/imm32
24072       0f 84/jump-if-= break/disp32
24073 $check-mu-call:check-output-type:
24074       # var v/eax: (addr v) = lookup(outputs->value)
24075       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
24076       # var t/ebx: (addr type-tree) = lookup(v->type)
24077       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
24078       89/<- %ebx 0/r32/eax
24079       # if (outputs->is-deref?) t = t->right  # TODO: check that t->left is an addr
24080       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
24081       {
24082         74/jump-if-= break/disp8
24083         (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
24084         89/<- %ebx 0/r32/eax
24085       }
24086       # var v2/eax: (addr v) = lookup(expected->value)
24087       (lookup *edx *(edx+4))  # List-value List-value => eax
24088       # var t2/eax: (addr type-tree) = lookup(v2->type)
24089       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
24090       # if (t != t2) error
24091       (type-match? %eax %ebx *(ebp-4))  # => eax
24092       3d/compare-eax-and 0/imm32/false
24093       {
24094         0f 85/jump-if-!= break/disp32
24095         (write-buffered *(ebp+0x14) "fn ")
24096         8b/-> *(ebp+0x10) 0/r32/eax
24097         (lookup *eax *(eax+4))  # Function-name Function-name => eax
24098         (write-buffered *(ebp+0x14) %eax)
24099         (write-buffered *(ebp+0x14) ": call ")
24100         (lookup *edi *(edi+4))  # Function-name Function-name => eax
24101         (write-buffered *(ebp+0x14) %eax)
24102         (write-buffered *(ebp+0x14) ": type for output '")
24103         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
24104         (lookup *eax *(eax+4))  # Var-name Var-name => eax
24105         (write-buffered *(ebp+0x14) %eax)
24106         (write-buffered *(ebp+0x14) "' is not right\n")
24107         (flush *(ebp+0x14))
24108         (stop *(ebp+0x18) 1)
24109       }
24110 $check-mu-call:check-output-register:
24111       # var v/eax: (addr v) = lookup(outputs->value)
24112       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
24113       # var r/ebx: (addr array byte) = lookup(v->register)
24114       (lookup *(eax+18) *(eax+0x1c))  # Var-register Var-register => eax
24115       89/<- %ebx 0/r32/eax
24116       # if (r == 0) error
24117       3d/compare-eax-and 0/imm32
24118       {
24119         0f 85/jump-if-!= break/disp32
24120         (write-buffered *(ebp+0x14) "fn ")
24121         8b/-> *(ebp+0x10) 0/r32/eax
24122         (lookup *eax *(eax+4))  # Function-name Function-name => eax
24123         (write-buffered *(ebp+0x14) %eax)
24124         (write-buffered *(ebp+0x14) ": call ")
24125         (lookup *edi *(edi+4))  # Function-name Function-name => eax
24126         (write-buffered *(ebp+0x14) %eax)
24127         (write-buffered *(ebp+0x14) ": output '")
24128         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
24129         (lookup *eax *(eax+4))  # Var-name Var-name => eax
24130         (write-buffered *(ebp+0x14) %eax)
24131         (write-buffered *(ebp+0x14) "' is not in a register\n")
24132         (flush *(ebp+0x14))
24133         (stop *(ebp+0x18) 1)
24134       }
24135       # var v2/eax: (addr v) = lookup(expected->value)
24136       (lookup *edx *(edx+4))  # Stmt-var-value Stmt-var-value => eax
24137       # var r2/eax: (addr array byte) = lookup(v2->register)
24138       (lookup *(eax+18) *(eax+0x1c))  # Var-register Var-register => eax
24139       # if (r != r2) error
24140       (string-equal? %eax %ebx)  # => eax
24141       3d/compare-eax-and 0/imm32/false
24142       {
24143         0f 85/jump-if-!= break/disp32
24144         (write-buffered *(ebp+0x14) "fn ")
24145         8b/-> *(ebp+0x10) 0/r32/eax
24146         (lookup *eax *(eax+4))  # Function-name Function-name => eax
24147         (write-buffered *(ebp+0x14) %eax)
24148         (write-buffered *(ebp+0x14) ": call ")
24149         (lookup *edi *(edi+4))  # Function-name Function-name => eax
24150         (write-buffered *(ebp+0x14) %eax)
24151         (write-buffered *(ebp+0x14) ": register for output '")
24152         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
24153         (lookup *eax *(eax+4))  # Var-name Var-name => eax
24154         (write-buffered *(ebp+0x14) %eax)
24155         (write-buffered *(ebp+0x14) "' is not right\n")
24156         (flush *(ebp+0x14))
24157         (stop *(ebp+0x18) 1)
24158       }
24159 $check-mu-call:continue-to-next-output:
24160       # outputs = lookup(outputs->next)
24161       (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
24162       89/<- %ecx 0/r32/eax
24163       # expected = lookup(expected->next)
24164       (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
24165       89/<- %edx 0/r32/eax
24166       #
24167       e9/jump loop/disp32
24168     }
24169 $check-mu-call:check-output-count:
24170     # if (outputs == expected) proceed
24171     39/compare %ecx 2/r32/edx
24172     {
24173       0f 84/jump-if-= break/disp32
24174       # exactly one of the two is null
24175       # if (outputs == 0) error("too many outputs")
24176       {
24177         81 7/subop/compare %ecx 0/imm32
24178         0f 84/jump-if-= break/disp32
24179         (write-buffered *(ebp+0x14) "fn ")
24180         8b/-> *(ebp+0x10) 0/r32/eax
24181         (lookup *eax *(eax+4))  # Function-name Function-name => eax
24182         (write-buffered *(ebp+0x14) %eax)
24183         (write-buffered *(ebp+0x14) ": call ")
24184         (lookup *edi *(edi+4))  # Function-name Function-name => eax
24185         (write-buffered *(ebp+0x14) %eax)
24186         (write-buffered *(ebp+0x14) ": too many outputs\n")
24187         (flush *(ebp+0x14))
24188         (stop *(ebp+0x18) 1)
24189       }
24190       # if (expected == 0) error("too few outputs")
24191       {
24192         81 7/subop/compare %edx 0/imm32
24193         0f 84/jump-if-= break/disp32
24194         (write-buffered *(ebp+0x14) "fn ")
24195         8b/-> *(ebp+0x10) 0/r32/eax
24196         (lookup *eax *(eax+4))  # Function-name Function-name => eax
24197         (write-buffered *(ebp+0x14) %eax)
24198         (write-buffered *(ebp+0x14) ": call ")
24199         (lookup *edi *(edi+4))  # Function-name Function-name => eax
24200         (write-buffered *(ebp+0x14) %eax)
24201         (write-buffered *(ebp+0x14) ": too few outputs\n")
24202         (flush *(ebp+0x14))
24203         (stop *(ebp+0x18) 1)
24204       }
24205     }
24206 $check-mu-call:end:
24207     # . restore registers
24208     5f/pop-to-edi
24209     5e/pop-to-esi
24210     5b/pop-to-ebx
24211     5a/pop-to-edx
24212     59/pop-to-ecx
24213     58/pop-to-eax
24214     # . reclaim locals exclusively on the stack
24215     81 0/subop/add %esp 0x70/imm32
24216     # . epilogue
24217     89/<- %esp 5/r32/ebp
24218     5d/pop-to-ebp
24219     c3/return
24220 
24221 # like type-equal? but takes literals type parameters into account
24222 type-match?:  # def: (addr type-tree), call: (addr type-tree), type-parameters: (addr table (handle array byte) (addr type-tree)) -> result/eax: boolean
24223     # . prologue
24224     55/push-ebp
24225     89/<- %ebp 4/r32/esp
24226     # if (call is literal and def is numberlike) return true
24227     {
24228 $type-match?:check-literal-int:
24229       (is-simple-mu-type? *(ebp+0xc) 0)  # literal => eax
24230       3d/compare-eax-and 0/imm32/false
24231       74/jump-if-= break/disp8
24232       (is-mu-numberlike-output? *(ebp+8))  # => eax
24233       3d/compare-eax-and 0/imm32/false
24234       74/jump-if-= break/disp8
24235       b8/copy-to-eax 1/imm32/true
24236       e9/jump $type-match?:end/disp32
24237     }
24238     # if (call is literal-string and def is string) return true
24239     {
24240 $type-match?:check-literal-string:
24241       (is-simple-mu-type? *(ebp+0xc) 0x10)  # literal-string => eax
24242       3d/compare-eax-and 0/imm32/false
24243       74/jump-if-= break/disp8
24244       (is-mu-string-type? *(ebp+8))  # => eax
24245       3d/compare-eax-and 0/imm32/false
24246       74/jump-if-= break/disp8
24247       b8/copy-to-eax 1/imm32/true
24248       e9/jump $type-match?:end/disp32
24249     }
24250 $type-match?:baseline:
24251     # otherwise fall back
24252     (type-component-match? *(ebp+8) *(ebp+0xc) *(ebp+0x10))  # => eax
24253 $type-match?:end:
24254     # . epilogue
24255     89/<- %esp 5/r32/ebp
24256     5d/pop-to-ebp
24257     c3/return
24258 
24259 type-component-match?:  # def: (addr type-tree), call: (addr type-tree), type-parameters: (addr table (handle array byte) (addr type-tree)) -> result/eax: boolean
24260     # . prologue
24261     55/push-ebp
24262     89/<- %ebp 4/r32/esp
24263     # . save registers
24264     51/push-ecx
24265     52/push-edx
24266     53/push-ebx
24267     # ecx = def
24268     8b/-> *(ebp+8) 1/r32/ecx
24269     # edx = call
24270     8b/-> *(ebp+0xc) 2/r32/edx
24271 $type-component-match?:compare-addr:
24272     # if (def == call) return true
24273     8b/-> %ecx 0/r32/eax  # Var-type
24274     39/compare %edx 0/r32/eax  # Var-type
24275     b8/copy-to-eax 1/imm32/true
24276     0f 84/jump-if-= $type-component-match?:end/disp32
24277     # if (def == 0) return false
24278     b8/copy-to-eax 0/imm32/false
24279     81 7/subop/compare %ecx 0/imm32  # Type-tree-is-atom
24280     0f 84/jump-if-= $type-component-match?:end/disp32
24281     # if (call == 0) return false
24282     81 7/subop/compare %edx 0/imm32  # Type-tree-is-atom
24283     0f 84/jump-if-= $type-component-match?:end/disp32
24284     # if def is a type parameter, just check in type-parameters
24285     {
24286 $type-component-match?:check-type-parameter:
24287       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
24288       74/jump-if-= break/disp8
24289       81 7/subop/compare *(ecx+4) 0xa/imm32/type-parameter  # Type-tree-value
24290       75/jump-if-!= break/disp8
24291 $type-component-match?:type-parameter:
24292       (type-parameter-match? *(ecx+8) *(ecx+0xc)  %edx  *(ebp+0x10))  # => eax
24293       e9/jump $type-component-match?:end/disp32
24294     }
24295     # if def is a list containing just a type parameter, just check in type-parameters
24296     {
24297 $type-component-match?:check-list-type-parameter:
24298       # if def is a list..
24299       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
24300       75/jump-if-!= break/disp8
24301       #   ..that's a singleton
24302       81 7/subop/compare *(ecx+0xc) 0/imm32  # Type-tree-left
24303       75/jump-if-!= break/disp8
24304       #   ..and whose head is a type parameter
24305       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
24306       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
24307       74/jump-if-= break/disp8
24308       81 7/subop/compare *(eax+4) 0xa/imm32/type-parameter  # Type-tree-value
24309       75/jump-if-!= break/disp8
24310 $type-component-match?:list-type-parameter:
24311       (type-parameter-match? *(eax+8) *(eax+0xc)  %edx  *(ebp+0x10))  # => eax
24312       e9/jump $type-component-match?:end/disp32
24313     }
24314 $type-component-match?:compare-atom-state:
24315     # if (def->is-atom? != call->is-atom?) return false
24316     8b/-> *ecx 3/r32/ebx  # Type-tree-is-atom
24317     39/compare *edx 3/r32/ebx  # Type-tree-is-atom
24318     b8/copy-to-eax 0/imm32/false
24319     0f 85/jump-if-!= $type-component-match?:end/disp32
24320     # if def->is-atom? return (def->value == call->value)
24321     {
24322 $type-component-match?:check-atom:
24323       81 7/subop/compare %ebx 0/imm32/false
24324       74/jump-if-= break/disp8
24325 $type-component-match?:is-atom:
24326       8b/-> *(ecx+4) 0/r32/eax  # Type-tree-value
24327       39/compare *(edx+4) 0/r32/eax  # Type-tree-value
24328       0f 94/set-if-= %al
24329       81 4/subop/and %eax 0xff/imm32
24330       e9/jump $type-component-match?:end/disp32
24331     }
24332 $type-component-match?:check-left:
24333     # if (!type-component-match?(def->left, call->left)) return false
24334     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
24335     89/<- %ebx 0/r32/eax
24336     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
24337     (type-component-match? %ebx %eax *(ebp+0x10))  # => eax
24338     3d/compare-eax-and 0/imm32/false
24339     74/jump-if-= $type-component-match?:end/disp8
24340 $type-component-match?:check-right:
24341     # return type-component-match?(def->right, call->right)
24342     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
24343     89/<- %ebx 0/r32/eax
24344     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
24345     (type-component-match? %ebx %eax *(ebp+0x10))  # => eax
24346 $type-component-match?:end:
24347     # . restore registers
24348     5b/pop-to-ebx
24349     5a/pop-to-edx
24350     59/pop-to-ecx
24351     # . epilogue
24352     89/<- %esp 5/r32/ebp
24353     5d/pop-to-ebp
24354     c3/return
24355 
24356 type-parameter-match?:  # type-parameter-name: (handle array byte), type: (addr type-tree), type-parameters: (addr table (handle array byte) (addr type-tree)) -> result/eax: boolean
24357     # . prologue
24358     55/push-ebp
24359     89/<- %ebp 4/r32/esp
24360     # . save registers
24361     51/push-ecx
24362     #
24363     (get-or-insert-handle *(ebp+0x14)  *(ebp+8) *(ebp+0xc)  0xc)  # => eax
24364     # if parameter wasn't saved, save it
24365     {
24366       81 7/subop/compare *eax 0/imm32
24367       75/jump-if-!= break/disp8
24368       8b/-> *(ebp+0x10) 1/r32/ecx
24369       89/<- *eax 1/r32/ecx
24370     }
24371     #
24372     (type-equal? *(ebp+0x10) *eax)  # => eax
24373 $type-parameter-match?:end:
24374     # . restore registers
24375     59/pop-to-ecx
24376     # . epilogue
24377     89/<- %esp 5/r32/ebp
24378     5d/pop-to-ebp
24379     c3/return
24380 
24381 size-of:  # v: (addr var) -> result/eax: int
24382     # . prologue
24383     55/push-ebp
24384     89/<- %ebp 4/r32/esp
24385     # . save registers
24386     51/push-ecx
24387     # var t/ecx: (addr type-tree) = lookup(v->type)
24388     8b/-> *(ebp+8) 1/r32/ecx
24389 #?     (write-buffered Stderr "size-of ")
24390 #?     (write-int32-hex-buffered Stderr %ecx)
24391 #?     (write-buffered Stderr Newline)
24392 #?     (write-buffered Stderr "type allocid: ")
24393 #?     (write-int32-hex-buffered Stderr *(ecx+8))
24394 #?     (write-buffered Stderr Newline)
24395 #?     (flush Stderr)
24396     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
24397     89/<- %ecx 0/r32/eax
24398     # if is-mu-array?(t) return size-of-array(t)
24399     {
24400       (is-mu-array? %ecx)  # => eax
24401       3d/compare-eax-and 0/imm32/false
24402       74/jump-if-= break/disp8
24403       (size-of-array %ecx)  # => eax
24404       eb/jump $size-of:end/disp8
24405     }
24406     # if is-mu-stream?(t) return size-of-stream(t)
24407     {
24408       (is-mu-stream? %ecx)  # => eax
24409       3d/compare-eax-and 0/imm32/false
24410       74/jump-if-= break/disp8
24411       (size-of-stream %ecx)  # => eax
24412       eb/jump $size-of:end/disp8
24413     }
24414     # if (!t->is-atom?) t = lookup(t->left)
24415     {
24416       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
24417       75/jump-if-!= break/disp8
24418       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
24419       89/<- %ecx 0/r32/eax
24420     }
24421     # TODO: assert t->is-atom?
24422     (size-of-type-id *(ecx+4))  # Type-tree-value => eax
24423 $size-of:end:
24424     # . restore registers
24425     59/pop-to-ecx
24426     # . epilogue
24427     89/<- %esp 5/r32/ebp
24428     5d/pop-to-ebp
24429     c3/return
24430 
24431 size-of-deref:  # v: (addr var) -> result/eax: int
24432     # . prologue
24433     55/push-ebp
24434     89/<- %ebp 4/r32/esp
24435     # . save registers
24436     51/push-ecx
24437     # var t/ecx: (addr type-tree) = lookup(v->type)
24438     8b/-> *(ebp+8) 1/r32/ecx
24439     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
24440     89/<- %ecx 0/r32/eax
24441     # TODO: assert(t is an addr)
24442     # t = lookup(t->right)
24443     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
24444     89/<- %ecx 0/r32/eax
24445     # if is-mu-array?(t) return size-of-array(t)
24446     {
24447       (is-mu-array? %ecx)  # => eax
24448       3d/compare-eax-and 0/imm32/false
24449       74/jump-if-= break/disp8
24450       (size-of-array %ecx)  # => eax
24451       eb/jump $size-of-deref:end/disp8
24452     }
24453     # if is-mu-stream?(t) return size-of-stream(t)
24454     {
24455       (is-mu-stream? %ecx)  # => eax
24456       3d/compare-eax-and 0/imm32/false
24457       74/jump-if-= break/disp8
24458       (size-of-stream %ecx)  # => eax
24459       eb/jump $size-of-deref:end/disp8
24460     }
24461     # if (!t->is-atom?) t = lookup(t->left)
24462     {
24463       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
24464       75/jump-if-!= break/disp8
24465       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
24466       89/<- %ecx 0/r32/eax
24467     }
24468     # TODO: assert t->is-atom?
24469     (size-of-type-id *(ecx+4))  # Type-tree-value => eax
24470 $size-of-deref:end:
24471     # . restore registers
24472     59/pop-to-ecx
24473     # . epilogue
24474     89/<- %esp 5/r32/ebp
24475     5d/pop-to-ebp
24476     c3/return
24477 
24478 is-mu-array?:  # t: (addr type-tree) -> result/eax: boolean
24479     # . prologue
24480     55/push-ebp
24481     89/<- %ebp 4/r32/esp
24482     # . save registers
24483     51/push-ecx
24484     # ecx = t
24485     8b/-> *(ebp+8) 1/r32/ecx
24486     # if t->is-atom?, return false
24487     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
24488     75/jump-if-!= $is-mu-array?:return-false/disp8
24489     # if !t->left->is-atom?, return false
24490     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
24491     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
24492     74/jump-if-= $is-mu-array?:return-false/disp8
24493     # return t->left->value == array
24494     81 7/subop/compare *(eax+4) 3/imm32/array-type-id  # Type-tree-value
24495     0f 94/set-if-= %al
24496     81 4/subop/and %eax 0xff/imm32
24497     eb/jump $is-mu-array?:end/disp8
24498 $is-mu-array?:return-false:
24499     b8/copy-to-eax 0/imm32/false
24500 $is-mu-array?:end:
24501     # . restore registers
24502     59/pop-to-ecx
24503     # . epilogue
24504     89/<- %esp 5/r32/ebp
24505     5d/pop-to-ebp
24506     c3/return
24507 
24508 # size of a statically allocated array where the size is part of the type expression
24509 size-of-array:  # a: (addr type-tree) -> result/eax: int
24510     # . prologue
24511     55/push-ebp
24512     89/<- %ebp 4/r32/esp
24513     # . save registers
24514     51/push-ecx
24515     52/push-edx
24516     #
24517     8b/-> *(ebp+8) 1/r32/ecx
24518     # TODO: assert that a->left is 'array'
24519     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
24520     89/<- %ecx 0/r32/eax
24521     # var elem-type/edx: type-id = a->right->left->value
24522     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
24523     8b/-> *(eax+4) 2/r32/edx  # Type-tree-value
24524     # TODO: assert that a->right->right->left->value == size
24525     # var array-size/ecx: int = a->right->right->left->value-size
24526     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
24527     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
24528     8b/-> *(eax+8) 1/r32/ecx  # Type-tree-value-size
24529     # return 4 + array-size * size-of(elem-type)
24530     (size-of-type-id-as-array-element %edx)  # => eax
24531     f7 4/subop/multiply-into-edx-eax %ecx
24532     05/add-to-eax 4/imm32  # for array size
24533     # TODO: check edx for overflow
24534 $size-of-array:end:
24535     # . restore registers
24536     5a/pop-to-edx
24537     59/pop-to-ecx
24538     # . epilogue
24539     89/<- %esp 5/r32/ebp
24540     5d/pop-to-ebp
24541     c3/return
24542 
24543 is-mu-stream?:  # t: (addr type-tree) -> result/eax: boolean
24544     # . prologue
24545     55/push-ebp
24546     89/<- %ebp 4/r32/esp
24547     # . save registers
24548     51/push-ecx
24549     # ecx = t
24550     8b/-> *(ebp+8) 1/r32/ecx
24551     # if t->is-atom?, return false
24552     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
24553     75/jump-if-!= $is-mu-stream?:return-false/disp8
24554     # if !t->left->is-atom?, return false
24555     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
24556     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
24557     74/jump-if-= $is-mu-stream?:return-false/disp8
24558     # return t->left->value == stream
24559     81 7/subop/compare *(eax+4) 0xb/imm32/stream-type-id  # Type-tree-value
24560     0f 94/set-if-= %al
24561     81 4/subop/and %eax 0xff/imm32
24562     eb/jump $is-mu-stream?:end/disp8
24563 $is-mu-stream?:return-false:
24564     b8/copy-to-eax 0/imm32/false
24565 $is-mu-stream?:end:
24566     # . restore registers
24567     59/pop-to-ecx
24568     # . epilogue
24569     89/<- %esp 5/r32/ebp
24570     5d/pop-to-ebp
24571     c3/return
24572 
24573 # size of a statically allocated stream where the size is part of the type expression
24574 size-of-stream:  # a: (addr type-tree) -> result/eax: int
24575     # . prologue
24576     55/push-ebp
24577     89/<- %ebp 4/r32/esp
24578     #
24579     (size-of-array *(ebp+8))  # assumes we ignore the actual type name 'array' in the type
24580     05/add-to-eax 8/imm32  # for read/write pointers
24581 $size-of-stream:end:
24582     # . epilogue
24583     89/<- %esp 5/r32/ebp
24584     5d/pop-to-ebp
24585     c3/return
24586 
24587 size-of-type-id:  # t: type-id -> result/eax: int
24588     # . prologue
24589     55/push-ebp
24590     89/<- %ebp 4/r32/esp
24591     # . save registers
24592     51/push-ecx
24593     # var out/ecx: (handle typeinfo)
24594     68/push 0/imm32
24595     68/push 0/imm32
24596     89/<- %ecx 4/r32/esp
24597     # eax = t
24598     8b/-> *(ebp+8) 0/r32/eax
24599     # if t is a literal, return 0
24600     3d/compare-eax-and 0/imm32
24601     0f 84/jump-if-= $size-of-type-id:end/disp32  # eax changes type from type-id to int
24602     # if t is a byte, return 4 (because we don't really support non-multiples of 4)
24603     3d/compare-eax-and 8/imm32/byte
24604     {
24605       75/jump-if-!= break/disp8
24606       b8/copy-to-eax 4/imm32
24607       eb/jump $size-of-type-id:end/disp8
24608     }
24609     # if t is a handle, return 8
24610     3d/compare-eax-and 4/imm32/handle
24611     {
24612       75/jump-if-!= break/disp8
24613       b8/copy-to-eax 8/imm32
24614       eb/jump $size-of-type-id:end/disp8  # eax changes type from type-id to int
24615     }
24616     # if t is a slice, return 8
24617     3d/compare-eax-and 0xc/imm32/slice
24618     {
24619       75/jump-if-!= break/disp8
24620       b8/copy-to-eax 8/imm32
24621       eb/jump $size-of-type-id:end/disp8  # eax changes type from type-id to int
24622     }
24623     # if t is a user-defined type, return its size
24624     # TODO: support non-atom type
24625     (find-typeinfo %eax %ecx)
24626     {
24627       81 7/subop/compare *ecx 0/imm32
24628       74/jump-if-= break/disp8
24629 $size-of-type-id:user-defined:
24630       (lookup *ecx *(ecx+4))  # => eax
24631       8b/-> *(eax+0xc) 0/r32/eax  # Typeinfo-total-size-in-bytes
24632       eb/jump $size-of-type-id:end/disp8
24633     }
24634     # otherwise return the word size
24635     b8/copy-to-eax 4/imm32
24636 $size-of-type-id:end:
24637     # . reclaim locals
24638     81 0/subop/add %esp 8/imm32
24639     # . restore registers
24640     59/pop-to-ecx
24641     # . epilogue
24642     89/<- %esp 5/r32/ebp
24643     5d/pop-to-ebp
24644     c3/return
24645 
24646 # Minor violation of our type system since it returns an addr. But we could
24647 # replace it with a handle some time.
24648 # Returns null if t is an atom.
24649 type-tail:  # t: (addr type-tree) -> out/eax: (addr type-tree)
24650     # . prologue
24651     55/push-ebp
24652     89/<- %ebp 4/r32/esp
24653     # . save registers
24654     51/push-ecx
24655     # eax = 0
24656     b8/copy-to-eax 0/imm32
24657     # ecx = t
24658     8b/-> *(ebp+8) 1/r32/ecx
24659 $type-tail:check-atom:
24660     # if t->is-atom? return 0
24661     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
24662     0f 85/jump-if-!= $type-tail:end/disp32
24663     # var tail = t->right
24664     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
24665     89/<- %ecx 0/r32/eax
24666 $type-tail:check-singleton:
24667     # if (tail->right == 0) return tail->left
24668     {
24669       81 7/subop/compare *(ecx+0xc) 0/imm32  # Type-tree-right
24670       75/jump-if-!= break/disp8
24671       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
24672       e9/jump $type-tail:end/disp32
24673     }
24674     # if tail->right->left is an array-capacity, return tail->left
24675     {
24676 $type-tail:check-array-capacity:
24677       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
24678       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
24679       75/jump-if-!= break/disp8
24680 $type-tail:check-array-capacity-1:
24681       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
24682       3d/compare-eax-and 0/imm32
24683       74/jump-if-= break/disp8
24684 $type-tail:check-array-capacity-2:
24685       (is-simple-mu-type? %eax 9)  # array-capacity => eax
24686       3d/compare-eax-and 0/imm32/false
24687       74/jump-if-= break/disp8
24688 $type-tail:array-capacity:
24689       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
24690       eb/jump $type-tail:end/disp8
24691     }
24692 $type-tail:check-compound-left:
24693     # if !tail->left->is-atom? return tail->left
24694     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
24695     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
24696     74/jump-if-= $type-tail:end/disp8
24697 $type-tail:return-tail:
24698     # return tail
24699     89/<- %eax 1/r32/ecx
24700 $type-tail:end:
24701     # . restore registers
24702     59/pop-to-ecx
24703     # . epilogue
24704     89/<- %esp 5/r32/ebp
24705     5d/pop-to-ebp
24706     c3/return
24707 
24708 type-equal?:  # a: (addr type-tree), b: (addr type-tree) -> result/eax: boolean
24709     # . prologue
24710     55/push-ebp
24711     89/<- %ebp 4/r32/esp
24712     # . save registers
24713     51/push-ecx
24714     52/push-edx
24715     53/push-ebx
24716     # ecx = a
24717     8b/-> *(ebp+8) 1/r32/ecx
24718     # edx = b
24719     8b/-> *(ebp+0xc) 2/r32/edx
24720 $type-equal?:compare-addr:
24721     # if (a == b) return true
24722     8b/-> %ecx 0/r32/eax  # Var-type
24723     39/compare %edx 0/r32/eax  # Var-type
24724     b8/copy-to-eax 1/imm32/true
24725     0f 84/jump-if-= $type-equal?:end/disp32
24726 $type-equal?:compare-null-a:
24727     # if (a == 0) return false
24728     b8/copy-to-eax 0/imm32/false
24729     81 7/subop/compare %ecx 0/imm32
24730     0f 84/jump-if-= $type-equal?:end/disp32
24731 $type-equal?:compare-null-b:
24732     # if (b == 0) return false
24733     81 7/subop/compare %edx 0/imm32
24734     0f 84/jump-if-= $type-equal?:end/disp32
24735 $type-equal?:compare-atom-state:
24736     # if (a->is-atom? != b->is-atom?) return false
24737     8b/-> *ecx 3/r32/ebx  # Type-tree-is-atom
24738     39/compare *edx 3/r32/ebx  # Type-tree-is-atom
24739     b8/copy-to-eax 0/imm32/false
24740     0f 85/jump-if-!= $type-equal?:end/disp32
24741     # if a->is-atom? return (a->value == b->value)
24742     {
24743 $type-equal?:check-atom:
24744       81 7/subop/compare %ebx 0/imm32/false
24745       74/jump-if-= break/disp8
24746 $type-equal?:is-atom:
24747       8b/-> *(ecx+4) 0/r32/eax  # Type-tree-value
24748       39/compare *(edx+4) 0/r32/eax  # Type-tree-value
24749       0f 94/set-if-= %al
24750       81 4/subop/and %eax 0xff/imm32
24751       e9/jump $type-equal?:end/disp32
24752     }
24753 $type-equal?:check-left:
24754     # if (!type-equal?(a->left, b->left)) return false
24755     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
24756     89/<- %ebx 0/r32/eax
24757     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
24758     (type-equal? %eax %ebx)  # => eax
24759     3d/compare-eax-and 0/imm32/false
24760     74/jump-if-= $type-equal?:end/disp8
24761 $type-equal?:check-right:
24762     # return type-equal?(a->right, b->right)
24763     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
24764     89/<- %ebx 0/r32/eax
24765     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
24766     (type-equal? %eax %ebx)  # => eax
24767 $type-equal?:end:
24768     # . restore registers
24769     5b/pop-to-ebx
24770     5a/pop-to-edx
24771     59/pop-to-ecx
24772     # . epilogue
24773     89/<- %esp 5/r32/ebp
24774     5d/pop-to-ebp
24775     c3/return
24776 
24777 #######################################################
24778 # Code-generation
24779 #######################################################
24780 
24781 == data
24782 
24783 # Global state added to each var record when performing code-generation.
24784 Curr-local-stack-offset:  # (addr int)
24785     0/imm32
24786 
24787 == code
24788 
24789 # We may not need to pass err/ed everywhere here. I think they're relics of Mu
24790 # getting type checks later in life.
24791 # But we do need them for runtime checks, particularly array index bounds checks.
24792 # So perhaps it's not worth taking them out. They're a safety net.
24793 
24794 emit-subx:  # out: (addr buffered-file), err: (addr buffered-file), ed: (addr exit-descriptor)
24795     # . prologue
24796     55/push-ebp
24797     89/<- %ebp 4/r32/esp
24798     # . save registers
24799     50/push-eax
24800     # var curr/eax: (addr function) = *Program->functions
24801     (lookup *_Program-functions *_Program-functions->payload)  # => eax
24802     {
24803       # if (curr == null) break
24804       3d/compare-eax-and 0/imm32
24805       0f 84/jump-if-= break/disp32
24806       (emit-subx-function *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10))
24807       # curr = lookup(curr->next)
24808       (lookup *(eax+0x20) *(eax+0x24))  # Function-next Function-next => eax
24809       e9/jump loop/disp32
24810     }
24811 $emit-subx:end:
24812     # . restore registers
24813     58/pop-to-eax
24814     # . epilogue
24815     89/<- %esp 5/r32/ebp
24816     5d/pop-to-ebp
24817     c3/return
24818 
24819 emit-subx-function:  # out: (addr buffered-file), f: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
24820     # . prologue
24821     55/push-ebp
24822     89/<- %ebp 4/r32/esp
24823     # some preprocessing
24824     (populate-mu-type-offsets-in-inouts *(ebp+0xc))
24825     # . save registers
24826     50/push-eax
24827     51/push-ecx
24828     52/push-edx
24829     # initialize some global state
24830     c7 0/subop/copy *Curr-block-depth 1/imm32  # Important: keep this in sync with the parse phase
24831     c7 0/subop/copy *Curr-local-stack-offset 0/imm32
24832     # ecx = f
24833     8b/-> *(ebp+0xc) 1/r32/ecx
24834     # var vars/edx: (stack (addr var) 256)
24835     81 5/subop/subtract %esp 0xc00/imm32
24836     68/push 0xc00/imm32/size
24837     68/push 0/imm32/top
24838     89/<- %edx 4/r32/esp
24839     # var name/eax: (addr array byte) = lookup(f->name)
24840     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
24841     #
24842     (write-buffered *(ebp+8) %eax)
24843     (write-buffered *(ebp+8) ":\n")
24844     (emit-subx-prologue *(ebp+8))
24845     # var body/eax: (addr block) = lookup(f->body)
24846     (lookup *(ecx+0x18) *(ecx+0x1c))  # Function-body Function-body => eax
24847     #
24848     (emit-subx-block *(ebp+8) %eax %edx *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
24849     (emit-subx-epilogue *(ebp+8))
24850     # TODO: validate that *Curr-block-depth and *Curr-local-stack-offset have
24851     # been cleaned up
24852 $emit-subx-function:end:
24853     # . reclaim locals
24854     81 0/subop/add %esp 0xc08/imm32
24855     # . restore registers
24856     5a/pop-to-edx
24857     59/pop-to-ecx
24858     58/pop-to-eax
24859     # . epilogue
24860     89/<- %esp 5/r32/ebp
24861     5d/pop-to-ebp
24862     c3/return
24863 
24864 populate-mu-type-offsets-in-inouts:  # f: (addr function)
24865     # . prologue
24866     55/push-ebp
24867     89/<- %ebp 4/r32/esp
24868     # . save registers
24869     50/push-eax
24870     51/push-ecx
24871     52/push-edx
24872     53/push-ebx
24873     57/push-edi
24874     # var next-offset/edx: int = 8
24875     ba/copy-to-edx 8/imm32
24876     # var curr/ecx: (addr list var) = lookup(f->inouts)
24877     8b/-> *(ebp+8) 1/r32/ecx
24878     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
24879     89/<- %ecx 0/r32/eax
24880     {
24881 $populate-mu-type-offsets-in-inouts:loop:
24882       81 7/subop/compare %ecx 0/imm32
24883       74/jump-if-= break/disp8
24884       # var v/ebx: (addr var) = lookup(curr->value)
24885       (lookup *ecx *(ecx+4))  # List-value List-value => eax
24886       89/<- %ebx 0/r32/eax
24887 #?       (lookup *ebx *(ebx+4))
24888 #?       (write-buffered Stderr "setting offset of fn inout ")
24889 #?       (write-buffered Stderr %eax)
24890 #?       (write-buffered Stderr "@")
24891 #?       (write-int32-hex-buffered Stderr %ebx)
24892 #?       (write-buffered Stderr " to ")
24893 #?       (write-int32-hex-buffered Stderr %edx)
24894 #?       (write-buffered Stderr Newline)
24895 #?       (flush Stderr)
24896       # v->offset = next-offset
24897       89/<- *(ebx+0x14) 2/r32/edx  # Var-offset
24898       # next-offset += size-of(v)
24899       (size-of %ebx)  # => eax
24900       01/add-to %edx 0/r32/eax
24901       # curr = lookup(curr->next)
24902       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
24903       89/<- %ecx 0/r32/eax
24904       #
24905       eb/jump loop/disp8
24906     }
24907 $populate-mu-type-offsets-in-inouts:end:
24908     # . restore registers
24909     5f/pop-to-edi
24910     5b/pop-to-ebx
24911     5a/pop-to-edx
24912     59/pop-to-ecx
24913     58/pop-to-eax
24914     # . epilogue
24915     89/<- %esp 5/r32/ebp
24916     5d/pop-to-ebp
24917     c3/return
24918 
24919 emit-subx-stmt-list:  # out: (addr buffered-file), stmts: (addr list stmt), vars: (addr stack live-var), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
24920     # . prologue
24921     55/push-ebp
24922     89/<- %ebp 4/r32/esp
24923     # . save registers
24924     50/push-eax
24925     51/push-ecx
24926     53/push-ebx
24927     56/push-esi
24928     # esi = stmts
24929     8b/-> *(ebp+0xc) 6/r32/esi
24930     #
24931     {
24932 $emit-subx-stmt-list:loop:
24933       81 7/subop/compare %esi 0/imm32
24934       0f 84/jump-if-= break/disp32
24935       # var curr-stmt/ecx: (addr stmt) = lookup(stmts->value)
24936       (lookup *esi *(esi+4))  # List-value List-value => eax
24937       89/<- %ecx 0/r32/eax
24938       {
24939 $emit-subx-stmt-list:check-for-block:
24940         81 7/subop/compare *ecx 0/imm32/block  # Stmt-tag
24941         75/jump-if-!= break/disp8
24942 $emit-subx-stmt-list:block:
24943         (emit-subx-block *(ebp+8) %ecx *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
24944       }
24945       {
24946 $emit-subx-stmt-list:check-for-stmt:
24947         81 7/subop/compare *ecx 1/imm32/stmt1  # Stmt-tag
24948         0f 85/jump-if-!= break/disp32
24949 $emit-subx-stmt-list:stmt1:
24950         {
24951           (is-mu-branch? %ecx)  # => eax
24952           3d/compare-eax-and 0/imm32/false
24953           0f 84/jump-if-= break/disp32
24954 $emit-subx-stmt-list:branch-stmt:
24955 +-- 25 lines: # unconditional return -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
24980 +-- 27 lines: # unconditional loops --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
25007 +-- 16 lines: # unconditional breaks -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
25023 +-- 38 lines: # simple conditional branches without a target -------------------------------------------------------------------------------------------------------------------------------------------------------
25061 +-- 19 lines: # conditional branches with an explicit target -------------------------------------------------------------------------------------------------------------------------------------------------------
25080         }
25081 $emit-subx-stmt-list:1-to-1:
25082         (emit-subx-stmt *(ebp+8) %ecx Primitives *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
25083         e9/jump $emit-subx-stmt-list:continue/disp32
25084       }
25085       {
25086 $emit-subx-stmt-list:check-for-var-def:
25087         81 7/subop/compare *ecx 2/imm32/var-def  # Stmt-tag
25088         75/jump-if-!= break/disp8
25089 $emit-subx-stmt-list:var-def:
25090         (emit-subx-var-def *(ebp+8) %ecx)
25091         (push *(ebp+0x10) *(ecx+4))  # Vardef-var
25092         (push *(ebp+0x10) *(ecx+8))  # Vardef-var
25093         (push *(ebp+0x10) 0)  # Live-var-register-spilled = 0 for vars on the stack
25094         #
25095         eb/jump $emit-subx-stmt-list:continue/disp8
25096       }
25097       {
25098 $emit-subx-stmt-list:check-for-reg-var-def:
25099         81 7/subop/compare *ecx 3/imm32/reg-var-def  # Stmt-tag
25100         0f 85/jump-if-!= break/disp32
25101 $emit-subx-stmt-list:reg-var-def:
25102         # TODO: ensure that there's exactly one output
25103         (push-output-and-maybe-emit-spill *(ebp+8) %ecx *(ebp+0x10) %esi *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
25104         # emit the instruction as usual
25105         (emit-subx-stmt *(ebp+8) %ecx Primitives *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
25106         #
25107         eb/jump $emit-subx-stmt-list:continue/disp8
25108       }
25109 $emit-subx-stmt-list:continue:
25110       # TODO: raise an error on unrecognized Stmt-tag
25111       (lookup *(esi+8) *(esi+0xc))  # List-next List-next => eax
25112       89/<- %esi 0/r32/eax
25113       e9/jump loop/disp32
25114     }
25115 $emit-subx-stmt-list:emit-cleanup:
25116     (emit-cleanup-code-until-depth *(ebp+8) *(ebp+0x10) *Curr-block-depth)
25117 $emit-subx-stmt-list:clean-up:
25118     (clean-up-stack-offset-state *(ebp+0x10) *Curr-block-depth)
25119     (clean-up-blocks *(ebp+0x10) *Curr-block-depth *(ebp+0x14))
25120 $emit-subx-stmt-list:end:
25121     # . restore registers
25122     5e/pop-to-esi
25123     5b/pop-to-ebx
25124     59/pop-to-ecx
25125     58/pop-to-eax
25126     # . epilogue
25127     89/<- %esp 5/r32/ebp
25128     5d/pop-to-ebp
25129     c3/return
25130 
25131 # 'later-stmts' includes 'stmt', but will behave the same even without it; reg-var-def stmts are guaranteed not to write to function outputs.
25132 push-output-and-maybe-emit-spill:  # out: (addr buffered-file), stmt: (addr reg-var-def), vars: (addr stack (handle var)), later-stmts: (addr list stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
25133     # . prologue
25134     55/push-ebp
25135     89/<- %ebp 4/r32/esp
25136     # . save registers
25137     50/push-eax
25138     51/push-ecx
25139     52/push-edx
25140     # ecx = stmt
25141     8b/-> *(ebp+0xc) 1/r32/ecx
25142     # var sv/eax: (addr stmt-var) = lookup(curr-stmt->outputs)
25143     (lookup *(ecx+0x14) *(ecx+0x18))  # Regvardef-outputs Regvardef-outputs => eax
25144     # TODO: assert !sv->is-deref?
25145     # var v/ecx: (addr var) = lookup(sv->value)
25146     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
25147     89/<- %ecx 0/r32/eax
25148     # v->block-depth = *Curr-block-depth
25149     8b/-> *Curr-block-depth 0/r32/eax
25150     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
25151 #?     (write-buffered Stderr "var ")
25152 #?     (lookup *ecx *(ecx+4))
25153 #?     (write-buffered Stderr %eax)
25154 #?     (write-buffered Stderr " at depth ")
25155 #?     (write-int32-hex-buffered Stderr *(ecx+0x10))
25156 #?     (write-buffered Stderr Newline)
25157 #?     (flush Stderr)
25158     # ensure that v is in a register
25159     81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
25160     0f 84/jump-if-= $push-output-and-maybe-emit-spill:abort/disp32
25161     # var emit-spill?/edx: boolean = not-yet-spilled-this-block? && will-not-write-some-register?(fn)
25162     (not-yet-spilled-this-block? %ecx *(ebp+0x10))  # => eax
25163     89/<- %edx 0/r32/eax
25164     3d/compare-eax-and 0/imm32/false
25165     0f 84/jump-if-= $push-output-and-maybe-emit-spill:push/disp32
25166     (will-not-write-some-register? %ecx *(ebp+0x14) *(ebp+0x18))  # => eax
25167     89/<- %edx 0/r32/eax
25168     # check emit-spill?
25169     3d/compare-eax-and 0/imm32/false
25170     0f 84/jump-if-= $push-output-and-maybe-emit-spill:push/disp32
25171     # TODO: assert(size-of(output) == 4)
25172     # *Curr-local-stack-offset -= 4
25173     81 5/subop/subtract *Curr-local-stack-offset 4/imm32
25174     # emit spill
25175     (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
25176     (emit-push-register *(ebp+8) %eax)
25177 $push-output-and-maybe-emit-spill:push:
25178     8b/-> *(ebp+0xc) 1/r32/ecx
25179     (lookup *(ecx+0x14) *(ecx+0x18))  # Regvardef-outputs Regvardef-outputs => eax
25180     # push(vars, {sv->value, emit-spill?})
25181     (push *(ebp+0x10) *eax)  # Stmt-var-value
25182     (push *(ebp+0x10) *(eax+4))  # Stmt-var-value
25183     (push *(ebp+0x10) %edx)
25184 $push-output-and-maybe-emit-spill:end:
25185     # . restore registers
25186     5a/pop-to-edx
25187     59/pop-to-ecx
25188     58/pop-to-eax
25189     # . epilogue
25190     89/<- %esp 5/r32/ebp
25191     5d/pop-to-ebp
25192     c3/return
25193 
25194 $push-output-and-maybe-emit-spill:abort:
25195     # error("var '" var->name "' initialized from an instruction must live in a register\n")
25196     (write-buffered *(ebp+0x1c) "var '")
25197     (write-buffered *(ebp+0x1c) *eax)  # Var-name
25198     (write-buffered *(ebp+0x1c) "' initialized from an instruction must live in a register\n")
25199     (flush *(ebp+0x1c))
25200     (stop *(ebp+0x20) 1)
25201     # never gets here
25202 
25203 emit-subx-cleanup-and-unconditional-nonlocal-branch:  # out: (addr buffered-file), stmt: (addr stmt1), vars: (addr stack live-var)
25204     # . prologue
25205     55/push-ebp
25206     89/<- %ebp 4/r32/esp
25207     # . save registers
25208     50/push-eax
25209     51/push-ecx
25210     # ecx = stmt
25211     8b/-> *(ebp+0xc) 1/r32/ecx
25212     # var target/eax: (addr array byte) = curr-stmt->inouts->value->name
25213     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25214     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
25215     (lookup *eax *(eax+4))  # Var-name Var-name => eax
25216     # clean up until target block
25217     (emit-cleanup-code-until-target *(ebp+8) *(ebp+0x10) %eax)
25218     # emit jump to target block
25219     (emit-indent *(ebp+8) *Curr-block-depth)
25220     (write-buffered *(ebp+8) "e9/jump ")
25221     (write-buffered *(ebp+8) %eax)
25222     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
25223     (string-starts-with? %eax "break")
25224     3d/compare-eax-and 0/imm32/false
25225     {
25226       74/jump-if-= break/disp8
25227       (write-buffered *(ebp+8) ":break/disp32\n")
25228       eb/jump $emit-subx-cleanup-and-unconditional-nonlocal-branch:end/disp8
25229     }
25230     (write-buffered *(ebp+8) ":loop/disp32\n")
25231 $emit-subx-cleanup-and-unconditional-nonlocal-branch:end:
25232     # . restore registers
25233     59/pop-to-ecx
25234     58/pop-to-eax
25235     # . epilogue
25236     89/<- %esp 5/r32/ebp
25237     5d/pop-to-ebp
25238     c3/return
25239 
25240 emit-outputs:  # out: (addr buffered-file), return-stmt: (addr stmt1), fn: (addr function)
25241     # pseudocode:
25242     #   for every inout, output in return-stmt, fn->outputs
25243     #     if inout is a literal
25244     #       c7 0/subop/copy %output inout/imm32
25245     #     otherwise
25246     #       8b/-> inout %output
25247     #
25248     # . prologue
25249     55/push-ebp
25250     89/<- %ebp 4/r32/esp
25251     # . save registers
25252     50/push-eax
25253     51/push-ecx
25254     56/push-esi
25255     57/push-edi
25256     # var curr-inout/esi: (addr stmt-var) = return-stmt->inouts
25257     8b/-> *(ebp+0xc) 0/r32/eax
25258     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
25259     89/<- %esi 0/r32/eax
25260     # var curr-output/edi: (addr list var) = fn->outputs
25261     8b/-> *(ebp+0x10) 0/r32/eax
25262     (lookup *(eax+0x10) *(eax+0x14))  # Function-outputs Function-outputs => eax
25263     89/<- %edi 0/r32/eax
25264     {
25265 $emit-outputs:loop:
25266       81 7/subop/compare %esi 0/imm32
25267       0f 84/jump-if-= break/disp32
25268       # emit copy to output register
25269       # var curr-var/ecx = lookup(curr-inout->value)
25270       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
25271       89/<- %ecx 0/r32/eax
25272       # if curr-var is a literal, emit copy of a literal to the output
25273       (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
25274       (is-simple-mu-type? %eax 0)  # literal => eax
25275       {
25276         3d/compare-eax-and 0/imm32/false
25277         0f 84/jump-if-= break/disp32
25278         (emit-indent *(ebp+8) *Curr-block-depth)
25279         (write-buffered *(ebp+8) "c7 0/subop/copy %")
25280         (lookup *edi *(edi+4))  # List-value List-value => eax
25281         (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
25282         (write-buffered *(ebp+8) %eax)
25283         (write-buffered *(ebp+8) " ")
25284         (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
25285         (write-buffered *(ebp+8) %eax)
25286         (write-buffered *(ebp+8) "/imm32\n")
25287         e9/jump $emit-outputs:continue/disp32
25288       }
25289       # if the non-literal is a register starting with "x", emit a floating-point copy
25290       (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
25291       {
25292         3d/compare-eax-and 0/imm32
25293         0f 84/jump-if-= break/disp32
25294         8a/copy-byte *(eax+4) 0/r32/AL
25295         81 4/subop/and %eax 0xff/imm32
25296         3d/compare-eax-and 0x78/imm32/x
25297         0f 85/jump-if-!= break/disp32
25298         (emit-indent *(ebp+8) *Curr-block-depth)
25299         (write-buffered *(ebp+8) "f3 0f 10/->")
25300         (emit-subx-var-as-rm32 *(ebp+8) %esi)
25301         (write-buffered *(ebp+8) " ")
25302         (lookup *edi *(edi+4))  # List-value List-value => eax
25303         (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
25304         (get Mu-registers %eax 0xc "Mu-registers")  # => eax
25305         (write-int32-hex-buffered *(ebp+8) *eax)
25306         (write-buffered *(ebp+8) "/x32\n")
25307         e9/jump $emit-outputs:continue/disp32
25308       }
25309       # otherwise emit an integer copy
25310       (emit-indent *(ebp+8) *Curr-block-depth)
25311       (write-buffered *(ebp+8) "8b/->")
25312       (emit-subx-var-as-rm32 *(ebp+8) %esi)
25313       (write-buffered *(ebp+8) " ")
25314       (lookup *edi *(edi+4))  # List-value List-value => eax
25315       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
25316       (get Mu-registers %eax 0xc "Mu-registers")  # => eax
25317       (write-int32-hex-buffered *(ebp+8) *eax)
25318       (write-buffered *(ebp+8) "/r32\n")
25319 $emit-outputs:continue:
25320       # curr-inout = curr-inout->next
25321       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
25322       89/<- %esi 0/r32/eax
25323       # curr-output = curr-output->next
25324       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
25325       89/<- %edi 0/r32/eax
25326       #
25327       e9/jump loop/disp32
25328     }
25329 $emit-outputs:end:
25330     # . restore registers
25331     5f/pop-to-edi
25332     5e/pop-to-esi
25333     59/pop-to-ecx
25334     58/pop-to-eax
25335     # . epilogue
25336     89/<- %esp 5/r32/ebp
25337     5d/pop-to-ebp
25338     c3/return
25339 
25340 is-mu-branch?:  # stmt: (addr stmt1) -> result/eax: boolean
25341     # . prologue
25342     55/push-ebp
25343     89/<- %ebp 4/r32/esp
25344     # . save registers
25345     51/push-ecx
25346     # ecx = lookup(stmt->operation)
25347     8b/-> *(ebp+8) 1/r32/ecx
25348     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
25349     89/<- %ecx 0/r32/eax
25350     # if (stmt->operation starts with "loop") return true
25351     (string-starts-with? %ecx "loop")  # => eax
25352     3d/compare-eax-and 0/imm32/false
25353     75/jump-if-not-equal $is-mu-branch?:end/disp8
25354     # if (stmt->operation starts with "break") return true
25355     (string-starts-with? %ecx "break")  # => eax
25356     3d/compare-eax-and 0/imm32/false
25357     75/jump-if-not-equal $is-mu-branch?:end/disp8
25358     # otherwise return (stmt->operation starts with "return")
25359     (string-starts-with? %ecx "return")  # => eax
25360 $is-mu-branch?:end:
25361     # . restore registers
25362     59/pop-to-ecx
25363     # . epilogue
25364     89/<- %esp 5/r32/ebp
25365     5d/pop-to-ebp
25366     c3/return
25367 
25368 emit-reverse-break:  # out: (addr buffered-file), stmt: (addr stmt1)
25369     # . prologue
25370     55/push-ebp
25371     89/<- %ebp 4/r32/esp
25372     # . save registers
25373     50/push-eax
25374     # eax = stmt
25375     8b/-> *(ebp+0xc) 0/r32/eax
25376     #
25377     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
25378     (get Reverse-branch %eax 0x10 "reverse-branch: ")  # => eax: (addr handle array byte)
25379     (emit-indent *(ebp+8) *Curr-block-depth)
25380     (lookup *eax *(eax+4))  # => eax
25381     (write-buffered *(ebp+8) %eax)
25382     (write-buffered *(ebp+8) " break/disp32\n")
25383 $emit-reverse-break:end:
25384     # . restore registers
25385     58/pop-to-eax
25386     # . epilogue
25387     89/<- %esp 5/r32/ebp
25388     5d/pop-to-ebp
25389     c3/return
25390 
25391 == data
25392 
25393 # Table from Mu branch instructions to the reverse SubX opcodes for them.
25394 Reverse-branch:  # (table (handle array byte) (handle array byte))
25395   # a table is a stream
25396   0x1c0/imm32/write
25397   0/imm32/read
25398   0x1c0/imm32/size
25399   # data
25400   0x11/imm32/alloc-id   _string-break-if-=/imm32                0x11/imm32/alloc-id   _string_0f_85_jump_label/imm32
25401   0x11/imm32/alloc-id   _string-loop-if-=/imm32                 0x11/imm32/alloc-id   _string_0f_85_jump_label/imm32
25402   0x11/imm32/alloc-id   _string-break-if-!=/imm32               0x11/imm32/alloc-id   _string_0f_84_jump_label/imm32
25403   0x11/imm32/alloc-id   _string-loop-if-!=/imm32                0x11/imm32/alloc-id   _string_0f_84_jump_label/imm32
25404   0x11/imm32/alloc-id   _string-break-if-</imm32                0x11/imm32/alloc-id   _string_0f_8d_jump_label/imm32
25405   0x11/imm32/alloc-id   _string-loop-if-</imm32                 0x11/imm32/alloc-id   _string_0f_8d_jump_label/imm32
25406   0x11/imm32/alloc-id   _string-break-if->/imm32                0x11/imm32/alloc-id   _string_0f_8e_jump_label/imm32
25407   0x11/imm32/alloc-id   _string-loop-if->/imm32                 0x11/imm32/alloc-id   _string_0f_8e_jump_label/imm32
25408   0x11/imm32/alloc-id   _string-break-if-<=/imm32               0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
25409   0x11/imm32/alloc-id   _string-loop-if-<=/imm32                0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
25410   0x11/imm32/alloc-id   _string-break-if->=/imm32               0x11/imm32/alloc-id   _string_0f_8c_jump_label/imm32
25411   0x11/imm32/alloc-id   _string-loop-if->=/imm32                0x11/imm32/alloc-id   _string_0f_8c_jump_label/imm32
25412   0x11/imm32/alloc-id   _string-break-if-addr</imm32            0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
25413   0x11/imm32/alloc-id   _string-loop-if-addr</imm32             0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
25414   0x11/imm32/alloc-id   _string-break-if-addr>/imm32            0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
25415   0x11/imm32/alloc-id   _string-loop-if-addr>/imm32             0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
25416   0x11/imm32/alloc-id   _string-break-if-addr<=/imm32           0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
25417   0x11/imm32/alloc-id   _string-loop-if-addr<=/imm32            0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
25418   0x11/imm32/alloc-id   _string-break-if-addr>=/imm32           0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
25419   0x11/imm32/alloc-id   _string-loop-if-addr>=/imm32            0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
25420   0x11/imm32/alloc-id   _string-break-if-float</imm32           0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
25421   0x11/imm32/alloc-id   _string-loop-if-float</imm32            0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
25422   0x11/imm32/alloc-id   _string-break-if-float>/imm32           0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
25423   0x11/imm32/alloc-id   _string-loop-if-float>/imm32            0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
25424   0x11/imm32/alloc-id   _string-break-if-float<=/imm32          0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
25425   0x11/imm32/alloc-id   _string-loop-if-float<=/imm32           0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
25426   0x11/imm32/alloc-id   _string-break-if-float>=/imm32          0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
25427   0x11/imm32/alloc-id   _string-loop-if-float>=/imm32           0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
25428 
25429 == code
25430 
25431 emit-unconditional-jump-to-depth:  # out: (addr buffered-file), vars: (addr stack live-var), depth: int, label-suffix: (addr array byte)
25432     # . prologue
25433     55/push-ebp
25434     89/<- %ebp 4/r32/esp
25435     # . save registers
25436     50/push-eax
25437     51/push-ecx
25438     52/push-edx
25439     53/push-ebx
25440     56/push-esi
25441     # ecx = vars
25442     8b/-> *(ebp+0xc) 1/r32/ecx
25443     # var eax: int = vars->top
25444     8b/-> *ecx 0/r32/eax
25445     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
25446     8d/copy-address *(ecx+eax-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
25447     # var min/ecx: (addr handle var) = vars->data
25448     8d/copy-address *(ecx+8) 1/r32/ecx
25449     # edx = depth
25450     8b/-> *(ebp+0x10) 2/r32/edx
25451     {
25452 $emit-unconditional-jump-to-depth:loop:
25453       # if (curr < min) break
25454       39/compare %esi 1/r32/ecx
25455       0f 82/jump-if-addr< break/disp32
25456       # var v/ebx: (addr var) = lookup(*curr)
25457       (lookup *esi *(esi+4))  # => eax
25458       89/<- %ebx 0/r32/eax
25459       # if (v->block-depth < until-block-depth) break
25460       39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
25461       0f 8c/jump-if-< break/disp32
25462       {
25463 $emit-unconditional-jump-to-depth:check:
25464         # if v->block-depth != until-block-depth, continue
25465         39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
25466         0f 85/jump-if-!= break/disp32
25467 $emit-unconditional-jump-to-depth:depth-found:
25468         # if v is not a literal, continue
25469         (size-of %ebx)  # => eax
25470         3d/compare-eax-and 0/imm32
25471         0f 85/jump-if-!= break/disp32
25472 $emit-unconditional-jump-to-depth:label-found:
25473         # emit unconditional jump, then return
25474         (emit-indent *(ebp+8) *Curr-block-depth)
25475         (write-buffered *(ebp+8) "e9/jump ")
25476         (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
25477         (write-buffered *(ebp+8) %eax)
25478         (write-buffered *(ebp+8) ":")
25479         (write-buffered *(ebp+8) *(ebp+0x14))
25480         (write-buffered *(ebp+8) "/disp32\n")
25481         eb/jump $emit-unconditional-jump-to-depth:end/disp8
25482       }
25483       # curr -= 12
25484       81 5/subop/subtract %esi 0xc/imm32
25485       e9/jump loop/disp32
25486     }
25487     # TODO: error if no label at 'depth' was found
25488 $emit-unconditional-jump-to-depth:end:
25489     # . restore registers
25490     5e/pop-to-esi
25491     5b/pop-to-ebx
25492     5a/pop-to-edx
25493     59/pop-to-ecx
25494     58/pop-to-eax
25495     # . epilogue
25496     89/<- %esp 5/r32/ebp
25497     5d/pop-to-ebp
25498     c3/return
25499 
25500 # emit clean-up code for 'vars' until some block depth
25501 # doesn't actually modify 'vars' so we need traverse manually inside the stack
25502 emit-cleanup-code-until-depth:  # out: (addr buffered-file), vars: (addr stack live-var), until-block-depth: int
25503     # . prologue
25504     55/push-ebp
25505     89/<- %ebp 4/r32/esp
25506     # . save registers
25507     50/push-eax
25508     51/push-ecx
25509     52/push-edx
25510     53/push-ebx
25511     56/push-esi
25512 #?     (write-buffered Stderr "--- cleanup\n")
25513 #?     (flush Stderr)
25514     # ecx = vars
25515     8b/-> *(ebp+0xc) 1/r32/ecx
25516     # var esi: int = vars->top
25517     8b/-> *ecx 6/r32/esi
25518     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
25519     8d/copy-address *(ecx+esi-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
25520     # var min/ecx: (addr handle var) = vars->data
25521     81 0/subop/add %ecx 8/imm32
25522     # edx = until-block-depth
25523     8b/-> *(ebp+0x10) 2/r32/edx
25524     {
25525 $emit-cleanup-code-until-depth:loop:
25526       # if (curr < min) break
25527       39/compare %esi 1/r32/ecx
25528       0f 82/jump-if-addr< break/disp32
25529       # var v/ebx: (addr var) = lookup(*curr)
25530       (lookup *esi *(esi+4))  # => eax
25531       89/<- %ebx 0/r32/eax
25532 #?       (lookup *ebx *(ebx+4))  # Var-name
25533 #?       (write-buffered Stderr "var ")
25534 #?       (write-buffered Stderr %eax)
25535 #?       (write-buffered Stderr Newline)
25536 #?       (flush Stderr)
25537       # if (v->block-depth < until-block-depth) break
25538       39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
25539       0f 8c/jump-if-< break/disp32
25540       # if v is in a register
25541       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
25542       {
25543         0f 84/jump-if-= break/disp32
25544         {
25545 $emit-cleanup-code-until-depth:check-for-previous-spill:
25546           8b/-> *(esi+8) 0/r32/eax  # Live-var-register-spilled
25547           3d/compare-eax-and 0/imm32/false
25548           74/jump-if-= break/disp8
25549 $emit-cleanup-code-until-depth:reclaim-var-in-register:
25550           (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
25551           (emit-pop-register *(ebp+8) %eax)
25552         }
25553         eb/jump $emit-cleanup-code-until-depth:continue/disp8
25554       }
25555       # otherwise v is on the stack
25556       {
25557         75/jump-if-!= break/disp8
25558 $emit-cleanup-code-until-depth:var-on-stack:
25559         (size-of %ebx)  # => eax
25560         # don't emit code for labels
25561         3d/compare-eax-and 0/imm32
25562         74/jump-if-= break/disp8
25563 $emit-cleanup-code-until-depth:reclaim-var-on-stack:
25564         (emit-indent *(ebp+8) *Curr-block-depth)
25565         (write-buffered *(ebp+8) "81 0/subop/add %esp ")
25566         (write-int32-hex-buffered *(ebp+8) %eax)
25567         (write-buffered *(ebp+8) "/imm32\n")
25568       }
25569 $emit-cleanup-code-until-depth:continue:
25570       # curr -= 12
25571       81 5/subop/subtract %esi 0xc/imm32
25572       e9/jump loop/disp32
25573     }
25574 $emit-cleanup-code-until-depth:end:
25575     # . restore registers
25576     5e/pop-to-esi
25577     5b/pop-to-ebx
25578     5a/pop-to-edx
25579     59/pop-to-ecx
25580     58/pop-to-eax
25581     # . epilogue
25582     89/<- %esp 5/r32/ebp
25583     5d/pop-to-ebp
25584     c3/return
25585 
25586 # emit clean-up code for 'vars' that don't conflict with output registers
25587 # doesn't actually modify 'vars' so we need traverse manually inside the stack
25588 emit-cleanup-code-for-non-outputs:  # out: (addr buffered-file), vars: (addr stack live-var), fn: (addr function)
25589     # . prologue
25590     55/push-ebp
25591     89/<- %ebp 4/r32/esp
25592     # . save registers
25593     50/push-eax
25594     51/push-ecx
25595     52/push-edx
25596     53/push-ebx
25597     56/push-esi
25598     57/push-edi
25599     # ecx = vars
25600     8b/-> *(ebp+0xc) 1/r32/ecx
25601     # var esi: int = vars->top
25602     8b/-> *ecx 6/r32/esi
25603     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
25604     8d/copy-address *(ecx+esi-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
25605     # var min/ecx: (addr handle var) = vars->data
25606     81 0/subop/add %ecx 8/imm32
25607     {
25608 $emit-cleanup-code-for-non-outputs:loop:
25609       # if (curr < min) break
25610       39/compare %esi 1/r32/ecx
25611       0f 82/jump-if-addr< break/disp32
25612       # var v/ebx: (addr var) = lookup(*curr)
25613       (lookup *esi *(esi+4))  # => eax
25614       89/<- %ebx 0/r32/eax
25615       # if v is in a register
25616       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
25617       {
25618         0f 84/jump-if-= break/disp32
25619         {
25620 $emit-cleanup-code-for-non-outputs:check-for-previous-spill:
25621           8b/-> *(esi+8) 0/r32/eax  # Live-var-register-spilled
25622           3d/compare-eax-and 0/imm32/false
25623           0f 84/jump-if-= break/disp32
25624 $emit-cleanup-code-for-non-outputs:reclaim-var-in-register:
25625           # var reg/edi: (addr array name) = v->register
25626           (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
25627           89/<- %edi 0/r32/eax
25628           # if reg is not in function outputs, emit a pop
25629           (reg-in-function-outputs? *(ebp+0x10) %edi)  # => eax
25630           3d/compare-eax-and 0/imm32/false
25631           {
25632             75/jump-if-!= break/disp8
25633             (emit-pop-register *(ebp+8) %edi)
25634             eb/jump $emit-cleanup-code-for-non-outputs:reclaim-var-in-register-done/disp8
25635           }
25636           # otherwise just drop it from the stack
25637           (emit-indent *(ebp+8) *Curr-block-depth)
25638           (write-buffered *(ebp+8) "81 0/subop/add %esp 4/imm32\n")
25639         }
25640 $emit-cleanup-code-for-non-outputs:reclaim-var-in-register-done:
25641         eb/jump $emit-cleanup-code-for-non-outputs:continue/disp8
25642       }
25643       # otherwise v is on the stack
25644       {
25645         75/jump-if-!= break/disp8
25646 $emit-cleanup-code-for-non-outputs:var-on-stack:
25647         (size-of %ebx)  # => eax
25648         # don't emit code for labels
25649         3d/compare-eax-and 0/imm32
25650         74/jump-if-= break/disp8
25651 $emit-cleanup-code-for-non-outputs:reclaim-var-on-stack:
25652         (emit-indent *(ebp+8) *Curr-block-depth)
25653         (write-buffered *(ebp+8) "81 0/subop/add %esp ")
25654         (write-int32-hex-buffered *(ebp+8) %eax)
25655         (write-buffered *(ebp+8) "/imm32\n")
25656       }
25657 $emit-cleanup-code-for-non-outputs:continue:
25658       # curr -= 12
25659       81 5/subop/subtract %esi 0xc/imm32
25660       e9/jump loop/disp32
25661     }
25662 $emit-cleanup-code-for-non-outputs:end:
25663     # . restore registers
25664     5f/pop-to-edi
25665     5e/pop-to-esi
25666     5b/pop-to-ebx
25667     5a/pop-to-edx
25668     59/pop-to-ecx
25669     58/pop-to-eax
25670     # . epilogue
25671     89/<- %esp 5/r32/ebp
25672     5d/pop-to-ebp
25673     c3/return
25674 
25675 emit-push-register:  # out: (addr buffered-file), reg: (addr array byte)
25676     # . prologue
25677     55/push-ebp
25678     89/<- %ebp 4/r32/esp
25679     # eax = reg
25680     8b/-> *(ebp+0xc) 0/r32/eax
25681     # var prefix/eax: byte = reg->data[0]
25682     8a/copy-byte *(eax+4) 0/r32/AL
25683     81 4/subop/and %eax 0xff/imm32
25684     # if (prefix == 'x') push xmm register
25685     {
25686       3d/compare-eax-and 0x78/imm32/x
25687       0f 85/jump-if-!= break/disp32
25688       # TODO validate register
25689       (emit-indent *(ebp+8) *Curr-block-depth)
25690       (write-buffered *(ebp+8) "81 5/subop/subtract %esp 4/imm32\n")
25691       (emit-indent *(ebp+8) *Curr-block-depth)
25692       (write-buffered *(ebp+8) "f3 0f 11/<- *esp ")
25693       # var prefix/eax: byte = reg->data[3]
25694       8b/-> *(ebp+0xc) 0/r32/eax
25695       8a/copy-byte *(eax+7) 0/r32/AL
25696       81 4/subop/and %eax 0xff/imm32
25697       (write-byte-buffered *(ebp+8) %eax)
25698       (write-buffered *(ebp+8) "/x32\n")
25699       e9/jump $emit-push-register:end/disp32
25700     }
25701     # otherwise push gp register
25702     (emit-indent *(ebp+8) *Curr-block-depth)
25703     (write-buffered *(ebp+8) "ff 6/subop/push %")
25704     (write-buffered *(ebp+8) *(ebp+0xc))
25705     (write-buffered *(ebp+8) Newline)
25706 $emit-push-register:end:
25707     # . epilogue
25708     89/<- %esp 5/r32/ebp
25709     5d/pop-to-ebp
25710     c3/return
25711 
25712 emit-pop-register:  # out: (addr buffered-file), reg: (addr array byte)
25713     # . prologue
25714     55/push-ebp
25715     89/<- %ebp 4/r32/esp
25716     # . save registers
25717     50/push-eax
25718     # eax = reg
25719     8b/-> *(ebp+0xc) 0/r32/eax
25720     # var prefix/eax: byte = reg->data[0]
25721     8a/copy-byte *(eax+4) 0/r32/AL
25722     81 4/subop/and %eax 0xff/imm32
25723     # if (prefix == 'x') pop to xmm register
25724     {
25725       3d/compare-eax-and 0x78/imm32/x
25726       0f 85/jump-if-!= break/disp32
25727       # TODO validate register
25728       (emit-indent *(ebp+8) *Curr-block-depth)
25729       (write-buffered *(ebp+8) "f3 0f 10/-> *esp ")
25730       # var prefix/eax: byte = reg->data[3]
25731       8b/-> *(ebp+0xc) 0/r32/eax
25732       8a/copy-byte *(eax+7) 0/r32/AL
25733       81 4/subop/and %eax 0xff/imm32
25734       (write-byte-buffered *(ebp+8) %eax)
25735       (write-buffered *(ebp+8) "/x32\n")
25736       (emit-indent *(ebp+8) *Curr-block-depth)
25737       (write-buffered *(ebp+8) "81 0/subop/add %esp 4/imm32\n")
25738       e9/jump $emit-pop-register:end/disp32
25739     }
25740     # otherwise pop to gp register
25741     (emit-indent *(ebp+8) *Curr-block-depth)
25742     (write-buffered *(ebp+8) "8f 0/subop/pop %")
25743     (write-buffered *(ebp+8) *(ebp+0xc))
25744     (write-buffered *(ebp+8) Newline)
25745 $emit-pop-register:end:
25746     # . restore registers
25747     58/pop-to-eax
25748     # . epilogue
25749     89/<- %esp 5/r32/ebp
25750     5d/pop-to-ebp
25751     c3/return
25752 
25753 # emit clean-up code for 'vars' until a given label is encountered
25754 # doesn't actually modify 'vars' so we need traverse manually inside the stack
25755 emit-cleanup-code-until-target:  # out: (addr buffered-file), vars: (addr stack live-var), until-block-label: (addr array byte)
25756     # . prologue
25757     55/push-ebp
25758     89/<- %ebp 4/r32/esp
25759     # . save registers
25760     50/push-eax
25761     51/push-ecx
25762     52/push-edx
25763     53/push-ebx
25764     # ecx = vars
25765     8b/-> *(ebp+0xc) 1/r32/ecx
25766     # var eax: int = vars->top
25767     8b/-> *ecx 0/r32/eax
25768     # var curr/edx: (addr handle var) = &vars->data[vars->top - 12]
25769     8d/copy-address *(ecx+eax-4) 2/r32/edx  # vars + 8 + vars->top - 12/Live-var-size
25770     # var min/ecx: (addr handle var) = vars->data
25771     81 0/subop/add %ecx 8/imm32
25772     {
25773 $emit-cleanup-code-until-target:loop:
25774       # if (curr < min) break
25775       39/compare %edx 1/r32/ecx
25776       0f 82/jump-if-addr< break/disp32
25777       # var v/ebx: (handle var) = lookup(*curr)
25778       (lookup *edx *(edx+4))  # => eax
25779       89/<- %ebx 0/r32/eax
25780       # if (v->name == until-block-label) break
25781       (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
25782       (string-equal? %eax *(ebp+0x10))  # => eax
25783       3d/compare-eax-and 0/imm32/false
25784       0f 85/jump-if-!= break/disp32
25785       # if v is in a register
25786       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
25787       {
25788         0f 84/jump-if-= break/disp32
25789         {
25790 $emit-cleanup-code-until-target:check-for-previous-spill:
25791           8b/-> *(edx+8) 0/r32/eax  # Live-var-register-spilled
25792           3d/compare-eax-and 0/imm32/false
25793           74/jump-if-= break/disp8
25794 $emit-cleanup-code-until-target:reclaim-var-in-register:
25795           (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
25796           (emit-pop-register *(ebp+8) %eax)
25797         }
25798         eb/jump $emit-cleanup-code-until-target:continue/disp8
25799       }
25800       # otherwise v is on the stack
25801       {
25802         75/jump-if-!= break/disp8
25803 $emit-cleanup-code-until-target:reclaim-var-on-stack:
25804         (size-of %ebx)  # => eax
25805         # don't emit code for labels
25806         3d/compare-eax-and 0/imm32
25807         74/jump-if-= break/disp8
25808         #
25809         (emit-indent *(ebp+8) *Curr-block-depth)
25810         (write-buffered *(ebp+8) "81 0/subop/add %esp ")
25811         (write-int32-hex-buffered *(ebp+8) %eax)
25812         (write-buffered *(ebp+8) "/imm32\n")
25813       }
25814 $emit-cleanup-code-until-target:continue:
25815       # curr -= 12
25816       81 5/subop/subtract %edx 0xc/imm32
25817       e9/jump loop/disp32
25818     }
25819 $emit-cleanup-code-until-target:end:
25820     # . restore registers
25821     5b/pop-to-ebx
25822     5a/pop-to-edx
25823     59/pop-to-ecx
25824     58/pop-to-eax
25825     # . epilogue
25826     89/<- %esp 5/r32/ebp
25827     5d/pop-to-ebp
25828     c3/return
25829 
25830 # update Curr-local-stack-offset assuming vars until some block depth are popped
25831 # doesn't actually modify 'vars', so we need traverse manually inside the stack
25832 clean-up-stack-offset-state:  # vars: (addr stack live-var), until-block-depth: int
25833     # . prologue
25834     55/push-ebp
25835     89/<- %ebp 4/r32/esp
25836     # . save registers
25837     50/push-eax
25838     51/push-ecx
25839     52/push-edx
25840     53/push-ebx
25841     56/push-esi
25842     # ecx = vars
25843     8b/-> *(ebp+8) 1/r32/ecx
25844     # var esi: int = vars->top
25845     8b/-> *ecx 6/r32/esi
25846     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
25847     8d/copy-address *(ecx+esi-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
25848     # var min/ecx: (addr handle var) = vars->data
25849     81 0/subop/add %ecx 8/imm32
25850     # edx = until-block-depth
25851     8b/-> *(ebp+0xc) 2/r32/edx
25852     {
25853 $clean-up-stack-offset-state:loop:
25854       # if (curr < min) break
25855       39/compare %esi 1/r32/ecx
25856       0f 82/jump-if-addr< break/disp32
25857       # var v/ebx: (addr var) = lookup(*curr)
25858       (lookup *esi *(esi+4))  # => eax
25859       89/<- %ebx 0/r32/eax
25860       # if (v->block-depth < until-block-depth) break
25861       39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
25862       0f 8c/jump-if-< break/disp32
25863       # if v is in a register
25864       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
25865       {
25866         0f 84/jump-if-= break/disp32
25867         {
25868 $clean-up-stack-offset-state:check-for-previous-spill:
25869           8b/-> *(esi+8) 0/r32/eax  # Live-var-register-spilled
25870           3d/compare-eax-and 0/imm32/false
25871           74/jump-if-= break/disp8
25872 $clean-up-stack-offset-state:reclaim-var-in-register:
25873           81 0/subop/add *Curr-local-stack-offset 4/imm32
25874         }
25875         eb/jump $clean-up-stack-offset-state:continue/disp8
25876       }
25877       # otherwise v is on the stack
25878       {
25879         75/jump-if-!= break/disp8
25880 $clean-up-stack-offset-state:var-on-stack:
25881         (size-of %ebx)  # => eax
25882         01/add-to *Curr-local-stack-offset 0/r32/eax
25883       }
25884 $clean-up-stack-offset-state:continue:
25885       # curr -= 12
25886       81 5/subop/subtract %esi 0xc/imm32
25887       e9/jump loop/disp32
25888     }
25889 $clean-up-stack-offset-state:end:
25890     # . restore registers
25891     5e/pop-to-esi
25892     5b/pop-to-ebx
25893     5a/pop-to-edx
25894     59/pop-to-ecx
25895     58/pop-to-eax
25896     # . epilogue
25897     89/<- %esp 5/r32/ebp
25898     5d/pop-to-ebp
25899     c3/return
25900 
25901 # Return true if there isn't a variable in 'vars' with the same block-depth
25902 # and register as 'v'.
25903 # 'v' is guaranteed not to be within 'vars'.
25904 not-yet-spilled-this-block?:  # v: (addr var), vars: (addr stack live-var) -> result/eax: boolean
25905     # . prologue
25906     55/push-ebp
25907     89/<- %ebp 4/r32/esp
25908     # . save registers
25909     51/push-ecx
25910     52/push-edx
25911     53/push-ebx
25912     56/push-esi
25913     57/push-edi
25914     # ecx = vars
25915     8b/-> *(ebp+0xc) 1/r32/ecx
25916     # var eax: int = vars->top
25917     8b/-> *ecx 0/r32/eax
25918     # var curr/edx: (addr handle var) = &vars->data[vars->top - 12]
25919     8d/copy-address *(ecx+eax-4) 2/r32/edx  # vars + 8 + vars->top - 12/Live-var-size
25920     # var min/ecx: (addr handle var) = vars->data
25921     8d/copy-address *(ecx+8) 1/r32/ecx
25922     # var depth/ebx: int = v->block-depth
25923     8b/-> *(ebp+8) 3/r32/ebx
25924     8b/-> *(ebx+0x10) 3/r32/ebx  # Var-block-depth
25925     # var needle/esi: (addr array byte) = v->register
25926     8b/-> *(ebp+8) 6/r32/esi
25927     (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
25928     89/<- %esi 0/r32/eax
25929     {
25930 $not-yet-spilled-this-block?:loop:
25931       # if (curr < min) break
25932       39/compare %edx 1/r32/ecx
25933       0f 82/jump-if-addr< break/disp32
25934       # var cand/edi: (addr var) = lookup(*curr)
25935       (lookup *edx *(edx+4))  # => eax
25936       89/<- %edi 0/r32/eax
25937       # if (cand->block-depth < depth) break
25938       39/compare *(edi+0x10) 3/r32/ebx  # Var-block-depth
25939       0f 8c/jump-if-< break/disp32
25940       # var cand-reg/edi: (array array byte) = cand->reg
25941       (lookup *(edi+0x18) *(edi+0x1c))  # Var-register Var-register => eax
25942       89/<- %edi 0/r32/eax
25943       # if (cand-reg == null) continue
25944       {
25945 $not-yet-spilled-this-block?:check-reg:
25946         81 7/subop/compare %edi 0/imm32
25947         0f 84/jump-if-= break/disp32
25948         # if (cand-reg == needle) return true
25949         (string-equal? %esi %edi)  # => eax
25950         3d/compare-eax-and 0/imm32/false
25951         74/jump-if-= break/disp8
25952 $not-yet-spilled-this-block?:return-false:
25953         b8/copy-to-eax 0/imm32/false
25954         eb/jump $not-yet-spilled-this-block?:end/disp8
25955       }
25956 $not-yet-spilled-this-block?:continue:
25957       # curr -= 12
25958       81 5/subop/subtract %edx 0xc/imm32
25959       e9/jump loop/disp32
25960     }
25961 $not-yet-spilled-this-block?:return-true:
25962     # return true
25963     b8/copy-to-eax 1/imm32/true
25964 $not-yet-spilled-this-block?:end:
25965     # . restore registers
25966     5f/pop-to-edi
25967     5e/pop-to-esi
25968     5b/pop-to-ebx
25969     5a/pop-to-edx
25970     59/pop-to-ecx
25971     # . epilogue
25972     89/<- %esp 5/r32/ebp
25973     5d/pop-to-ebp
25974     c3/return
25975 
25976 # could the register of 'v' ever be written to by one of the vars in fn-outputs?
25977 will-not-write-some-register?:  # v: (addr var), stmts: (addr list stmt), fn: (addr function) -> result/eax: boolean
25978     # . prologue
25979     55/push-ebp
25980     89/<- %ebp 4/r32/esp
25981     # eax = v
25982     8b/-> *(ebp+8) 0/r32/eax
25983     # var reg/eax: (addr array byte) = lookup(v->register)
25984     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
25985     # var target/eax: (addr var) = find-register(fn-outputs, reg)
25986     (find-register *(ebp+0x10) %eax)  # => eax
25987     # if (target == 0) return true
25988     {
25989       3d/compare-eax-and 0/imm32
25990       75/jump-if-!= break/disp8
25991       b8/copy-to-eax 1/imm32/true
25992       eb/jump $will-not-write-some-register?:end/disp8
25993     }
25994     # return !assigns-in-stmts?(stmts, target)
25995     (assigns-in-stmts? *(ebp+0xc) %eax)  # => eax
25996     3d/compare-eax-and 0/imm32/false
25997     # assume: true = 1, so no need to mask with 0x000000ff
25998     0f 94/set-if-= %al
25999 $will-not-write-some-register?:end:
26000     # . epilogue
26001     89/<- %esp 5/r32/ebp
26002     5d/pop-to-ebp
26003     c3/return
26004 
26005 # return fn output with matching register
26006 # always returns false if 'reg' is null
26007 find-register:  # fn: (addr function), reg: (addr array byte) -> result/eax: (addr var)
26008     # . prologue
26009     55/push-ebp
26010     89/<- %ebp 4/r32/esp
26011     # . save registers
26012     51/push-ecx
26013     # var curr/ecx: (addr list var) = lookup(fn->outputs)
26014     8b/-> *(ebp+8) 1/r32/ecx
26015     (lookup *(ecx+0x10) *(ecx+0x14))  # Function-outputs Function-outputs => eax
26016     89/<- %ecx 0/r32/eax
26017     {
26018 $find-register:loop:
26019       # if (curr == 0) break
26020       81 7/subop/compare %ecx 0/imm32
26021       74/jump-if-= break/disp8
26022       # eax = curr->value->register
26023       (lookup *ecx *(ecx+4))  # List-value List-value => eax
26024       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
26025       # if (eax == reg) return curr->value
26026 $find-register:compare:
26027       (string-equal? *(ebp+0xc) %eax)  # => eax
26028       {
26029         3d/compare-eax-and 0/imm32/false
26030         74/jump-if-= break/disp8
26031 $find-register:found:
26032         (lookup *ecx *(ecx+4))  # List-value List-value => eax
26033         eb/jump $find-register:end/disp8
26034       }
26035       # curr = lookup(curr->next)
26036       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
26037       89/<- %ecx 0/r32/eax
26038       #
26039       eb/jump loop/disp8
26040     }
26041 $find-register:end:
26042     # . restore registers
26043     59/pop-to-ecx
26044     # . epilogue
26045     89/<- %esp 5/r32/ebp
26046     5d/pop-to-ebp
26047     c3/return
26048 
26049 assigns-in-stmts?:  # stmts: (addr list stmt), v: (addr var) -> result/eax: boolean
26050     # . prologue
26051     55/push-ebp
26052     89/<- %ebp 4/r32/esp
26053     # . save registers
26054     51/push-ecx
26055     # var curr/ecx: (addr list stmt) = stmts
26056     8b/-> *(ebp+8) 1/r32/ecx
26057     {
26058       # if (curr == 0) break
26059       81 7/subop/compare %ecx 0/imm32
26060       74/jump-if-= break/disp8
26061       # if assigns-in-stmt?(curr->value, v) return true
26062       (lookup *ecx *(ecx+4))  # List-value List-value => eax
26063       (assigns-in-stmt? %eax *(ebp+0xc))  # => eax
26064       3d/compare-eax-and 0/imm32/false
26065       75/jump-if-!= break/disp8
26066       # curr = lookup(curr->next)
26067       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
26068       89/<- %ecx 0/r32/eax
26069       #
26070       eb/jump loop/disp8
26071     }
26072 $assigns-in-stmts?:end:
26073     # . restore registers
26074     59/pop-to-ecx
26075     # . epilogue
26076     89/<- %esp 5/r32/ebp
26077     5d/pop-to-ebp
26078     c3/return
26079 
26080 assigns-in-stmt?:  # stmt: (addr stmt), v: (addr var) -> result/eax: boolean
26081     # . prologue
26082     55/push-ebp
26083     89/<- %ebp 4/r32/esp
26084     # . save registers
26085     51/push-ecx
26086     # ecx = stmt
26087     8b/-> *(ebp+8) 1/r32/ecx
26088     # if stmt is a stmt1, return assigns-in-stmt-vars?(stmt->outputs, v)
26089     {
26090       81 7/subop/compare *ecx 1/imm32/stmt1  # Stmt-tag
26091       75/jump-if-!= break/disp8
26092       (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
26093       (assigns-in-stmt-vars? %eax *(ebp+0xc))  # => eax
26094       eb/jump $assigns-in-stmt?:end/disp8
26095     }
26096     # if stmt is a block, return assigns-in-stmts?(stmt->stmts, v)
26097     {
26098       81 7/subop/compare *ecx 0/imm32/block  # Stmt-tag
26099       75/jump-if-!= break/disp8
26100       (lookup *(ecx+4) *(ecx+8))  # Block-stmts Block-stmts => eax
26101       (assigns-in-stmts? %eax *(ebp+0xc))  # => eax
26102       eb/jump $assigns-in-stmt?:end/disp8
26103     }
26104     # otherwise return false
26105     b8/copy 0/imm32/false
26106 $assigns-in-stmt?:end:
26107     # . restore registers
26108     59/pop-to-ecx
26109     # . epilogue
26110     89/<- %esp 5/r32/ebp
26111     5d/pop-to-ebp
26112     c3/return
26113 
26114 assigns-in-stmt-vars?:  # stmt-var: (addr stmt-var), v: (addr var) -> result/eax: boolean
26115     # . prologue
26116     55/push-ebp
26117     89/<- %ebp 4/r32/esp
26118     # . save registers
26119     51/push-ecx
26120     # var curr/ecx: (addr stmt-var) = stmt-var
26121     8b/-> *(ebp+8) 1/r32/ecx
26122     {
26123       # if (curr == 0) break
26124       81 7/subop/compare %ecx 0/imm32
26125       74/jump-if-= break/disp8
26126       # eax = lookup(curr->value)
26127       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
26128       # if (eax == v  &&  curr->is-deref? == false) return true
26129       {
26130         39/compare *(ebp+0xc) 0/r32/eax
26131         75/jump-if-!= break/disp8
26132         81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
26133         75/jump-if-!= break/disp8
26134         b8/copy-to-eax 1/imm32/true
26135         eb/jump $assigns-in-stmt-vars?:end/disp8
26136       }
26137       # curr = lookup(curr->next)
26138       (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
26139       89/<- %ecx 0/r32/eax
26140       #
26141       eb/jump loop/disp8
26142     }
26143 $assigns-in-stmt-vars?:end:
26144     # . restore registers
26145     59/pop-to-ecx
26146     # . epilogue
26147     89/<- %esp 5/r32/ebp
26148     5d/pop-to-ebp
26149     c3/return
26150 
26151 # is there a var before 'v' with the same block-depth and register on the 'vars' stack?
26152 # v is guaranteed to be within vars
26153 # 'start' is provided as an optimization, a pointer within vars
26154 # *start == v
26155 same-register-spilled-before?:  # v: (addr var), vars: (addr stack (handle var)), start: (addr var) -> result/eax: boolean
26156     # . prologue
26157     55/push-ebp
26158     89/<- %ebp 4/r32/esp
26159     # . save registers
26160     51/push-ecx
26161     52/push-edx
26162     53/push-ebx
26163     56/push-esi
26164     57/push-edi
26165     # ecx = v
26166     8b/-> *(ebp+8) 1/r32/ecx
26167     # var reg/edx: (addr array byte) = lookup(v->register)
26168     (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
26169     89/<- %edx 0/r32/eax
26170     # var depth/ebx: int = v->block-depth
26171     8b/-> *(ecx+0x10) 3/r32/ebx  # Var-block-depth
26172     # var min/ecx: (addr handle var) = vars->data
26173     8b/-> *(ebp+0xc) 1/r32/ecx
26174     81 0/subop/add %ecx 8/imm32
26175     # TODO: check that start >= min and start < &vars->data[top]
26176     # TODO: check that *start == v
26177     # var curr/esi: (addr handle var) = start
26178     8b/-> *(ebp+0x10) 6/r32/esi
26179     # curr -= 8
26180     81 5/subop/subtract %esi 8/imm32
26181     {
26182 $same-register-spilled-before?:loop:
26183       # if (curr < min) break
26184       39/compare %esi 1/r32/ecx
26185       0f 82/jump-if-addr< break/disp32
26186       # var x/eax: (addr var) = lookup(*curr)
26187       (lookup *esi *(esi+4))  # => eax
26188       # if (x->block-depth < depth) break
26189       39/compare *(eax+0x10) 3/r32/ebx  # Var-block-depth
26190       0f 8c/jump-if-< break/disp32
26191       # if (x->register == 0) continue
26192       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
26193       74/jump-if-= $same-register-spilled-before?:continue/disp8
26194       # if (x->register == reg) return true
26195       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
26196       (string-equal? %eax %edx)  # => eax
26197       3d/compare-eax-and 0/imm32/false
26198       b8/copy-to-eax 1/imm32/true
26199       75/jump-if-!= $same-register-spilled-before?:end/disp8
26200 $same-register-spilled-before?:continue:
26201       # curr -= 8
26202       81 5/subop/subtract %esi 8/imm32
26203       e9/jump loop/disp32
26204     }
26205 $same-register-spilled-before?:false:
26206     b8/copy-to-eax 0/imm32/false
26207 $same-register-spilled-before?:end:
26208     # . restore registers
26209     5f/pop-to-edi
26210     5e/pop-to-esi
26211     5b/pop-to-ebx
26212     5a/pop-to-edx
26213     59/pop-to-ecx
26214     # . epilogue
26215     89/<- %esp 5/r32/ebp
26216     5d/pop-to-ebp
26217     c3/return
26218 
26219 # clean up global state for 'vars' until some block depth (inclusive)
26220 clean-up-blocks:  # vars: (addr stack live-var), until-block-depth: int, fn: (addr function)
26221     # . prologue
26222     55/push-ebp
26223     89/<- %ebp 4/r32/esp
26224     # . save registers
26225     50/push-eax
26226     51/push-ecx
26227     56/push-esi
26228     # esi = vars
26229     8b/-> *(ebp+8) 6/r32/esi
26230     # ecx = until-block-depth
26231     8b/-> *(ebp+0xc) 1/r32/ecx
26232     {
26233 $clean-up-blocks:reclaim-loop:
26234       # if (vars->top <= 0) break
26235       8b/-> *esi 0/r32/eax  # Stack-top
26236       3d/compare-eax-and 0/imm32
26237       0f 8e/jump-if-<= break/disp32
26238       # var v/eax: (addr var) = lookup(vars[vars->top-12])
26239       (lookup *(esi+eax-4) *(esi+eax))  # vars + 8 + vars->top - 12 => eax
26240       # if (v->block-depth < until-block-depth) break
26241       39/compare *(eax+0x10) 1/r32/ecx  # Var-block-depth
26242       0f 8c/jump-if-< break/disp32
26243       (pop %esi)  # => eax
26244       (pop %esi)  # => eax
26245       (pop %esi)  # => eax
26246       e9/jump loop/disp32
26247     }
26248 $clean-up-blocks:end:
26249     # . restore registers
26250     5e/pop-to-esi
26251     59/pop-to-ecx
26252     58/pop-to-eax
26253     # . epilogue
26254     89/<- %esp 5/r32/ebp
26255     5d/pop-to-ebp
26256     c3/return
26257 
26258 reg-in-function-outputs?:  # fn: (addr function), target: (addr array byte) -> result/eax: boolean
26259     # . prologue
26260     55/push-ebp
26261     89/<- %ebp 4/r32/esp
26262     # . save registers
26263     51/push-ecx
26264     # var curr/ecx: (addr list var) = lookup(fn->outputs)
26265     8b/-> *(ebp+8) 0/r32/eax
26266     (lookup *(eax+0x10) *(eax+0x14))  # Function-outputs Function-outputs => eax
26267     89/<- %ecx 0/r32/eax
26268     # while curr != null
26269     {
26270       81 7/subop/compare %ecx 0/imm32
26271       74/jump-if-= break/disp8
26272       # var v/eax: (addr var) = lookup(curr->value)
26273       (lookup *ecx *(ecx+4))  # List-value List-value => eax
26274       # var reg/eax: (addr array byte) = lookup(v->register)
26275       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
26276       # if (reg == target) return true
26277       (string-equal? %eax *(ebp+0xc))  # => eax
26278       3d/compare-eax-and 0/imm32/false
26279       75/jump-if-!= $reg-in-function-outputs?:end/disp8
26280       # curr = curr->next
26281       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
26282       89/<- %ecx 0/r32/eax
26283       #
26284       eb/jump loop/disp8
26285     }
26286     # return false
26287     b8/copy-to-eax 0/imm32
26288 $reg-in-function-outputs?:end:
26289     # . restore registers
26290     59/pop-to-ecx
26291     # . epilogue
26292     89/<- %esp 5/r32/ebp
26293     5d/pop-to-ebp
26294     c3/return
26295 
26296 emit-subx-var-def:  # out: (addr buffered-file), stmt: (addr stmt)
26297     # . prologue
26298     55/push-ebp
26299     89/<- %ebp 4/r32/esp
26300     # . save registers
26301     50/push-eax
26302     51/push-ecx
26303     52/push-edx
26304     # eax = stmt
26305     8b/-> *(ebp+0xc) 0/r32/eax
26306     # var v/ecx: (addr var)
26307     (lookup *(eax+4) *(eax+8))  # Vardef-var Vardef-var => eax
26308     89/<- %ecx 0/r32/eax
26309     # v->block-depth = *Curr-block-depth
26310     8b/-> *Curr-block-depth 0/r32/eax
26311     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
26312     # var n/edx: int = size-of(stmt->var)
26313     (size-of %ecx)  # => eax
26314     89/<- %edx 0/r32/eax
26315     # *Curr-local-stack-offset -= n
26316     29/subtract-from *Curr-local-stack-offset 2/r32/edx
26317     # v->offset = *Curr-local-stack-offset
26318     8b/-> *Curr-local-stack-offset 0/r32/eax
26319     89/<- *(ecx+0x14) 0/r32/eax  # Var-offset
26320     # if v is an array, do something special to initialize it
26321     {
26322       (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
26323       (is-mu-array? %eax)  # => eax
26324       3d/compare-eax-and 0/imm32/false
26325       0f 84/jump-if-= break/disp32
26326       # var array-size-without-size/edx: int = n-4
26327       81 5/subop/subtract %edx 4/imm32
26328       #
26329       (emit-array-data-initialization *(ebp+8) %edx)
26330       e9/jump $emit-subx-var-def:end/disp32
26331     }
26332     # another special-case for initializing streams
26333     # a stream is an array with 2 extra pointers
26334     {
26335       (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
26336       (is-mu-stream? %eax)  # => eax
26337       3d/compare-eax-and 0/imm32/false
26338       0f 84/jump-if-= break/disp32
26339       # var array-size-without-size/edx: int = n-12
26340       81 5/subop/subtract %edx 0xc/imm32
26341       (emit-array-data-initialization *(ebp+8) %edx)
26342       # emit read and write pointers
26343       (emit-indent *(ebp+8) *Curr-block-depth)
26344       (write-buffered *(ebp+8) "68/push 0/imm32\n")
26345       (emit-indent *(ebp+8) *Curr-block-depth)
26346       (write-buffered *(ebp+8) "68/push 0/imm32\n")
26347       #
26348       eb/jump $emit-subx-var-def:end/disp8
26349     }
26350     # while n > 0
26351     {
26352       81 7/subop/compare %edx 0/imm32
26353       7e/jump-if-<= break/disp8
26354       (emit-indent *(ebp+8) *Curr-block-depth)
26355       (write-buffered *(ebp+8) "68/push 0/imm32\n")
26356       # n -= 4
26357       81 5/subop/subtract %edx 4/imm32
26358       #
26359       eb/jump loop/disp8
26360     }
26361 $emit-subx-var-def:end:
26362     # . restore registers
26363     5a/pop-to-edx
26364     59/pop-to-ecx
26365     58/pop-to-eax
26366     # . epilogue
26367     89/<- %esp 5/r32/ebp
26368     5d/pop-to-ebp
26369     c3/return
26370 
26371 emit-array-data-initialization:  # out: (addr buffered-file), n: int
26372     # . prologue
26373     55/push-ebp
26374     89/<- %ebp 4/r32/esp
26375     #
26376     (emit-indent *(ebp+8) *Curr-block-depth)
26377     (write-buffered *(ebp+8) "(push-n-zero-bytes ")
26378     (write-int32-hex-buffered *(ebp+8) *(ebp+0xc))
26379     (write-buffered *(ebp+8) ")\n")
26380     (emit-indent *(ebp+8) *Curr-block-depth)
26381     (write-buffered *(ebp+8) "68/push ")
26382     (write-int32-hex-buffered *(ebp+8) *(ebp+0xc))
26383     (write-buffered *(ebp+8) "/imm32\n")
26384 $emit-array-data-initialization:end:
26385     # . epilogue
26386     89/<- %esp 5/r32/ebp
26387     5d/pop-to-ebp
26388     c3/return
26389 
26390 emit-subx-stmt:  # out: (addr buffered-file), stmt: (addr stmt), primitives: (addr primitive), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
26391     # . prologue
26392     55/push-ebp
26393     89/<- %ebp 4/r32/esp
26394     # . save registers
26395     50/push-eax
26396     51/push-ecx
26397     # - some special-case primitives that don't actually use the 'primitives' data structure
26398     # var op/ecx: (addr array byte) = lookup(stmt->operation)
26399     8b/-> *(ebp+0xc) 1/r32/ecx
26400     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
26401     89/<- %ecx 0/r32/eax
26402     # array size
26403     {
26404       # if (!string-equal?(stmt->operation, "length")) break
26405       (string-equal? %ecx "length")  # => eax
26406       3d/compare-eax-and 0/imm32
26407       0f 84/jump-if-= break/disp32
26408       (translate-mu-length-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
26409       e9/jump $emit-subx-stmt:end/disp32
26410     }
26411     # index into array
26412     {
26413       # if (!string-equal?(stmt->operation, "index")) break
26414       (string-equal? %ecx "index")  # => eax
26415       3d/compare-eax-and 0/imm32
26416       0f 84/jump-if-= break/disp32
26417       (translate-mu-index-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
26418       e9/jump $emit-subx-stmt:end/disp32
26419     }
26420     # compute-offset for index into array
26421     {
26422       # if (!string-equal?(stmt->operation, "compute-offset")) break
26423       (string-equal? %ecx "compute-offset")  # => eax
26424       3d/compare-eax-and 0/imm32
26425       0f 84/jump-if-= break/disp32
26426       (translate-mu-compute-index-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
26427       e9/jump $emit-subx-stmt:end/disp32
26428     }
26429     # get field from record
26430     {
26431       # if (!string-equal?(stmt->operation, "get")) break
26432       (string-equal? %ecx "get")  # => eax
26433       3d/compare-eax-and 0/imm32
26434       0f 84/jump-if-= break/disp32
26435       (translate-mu-get-stmt *(ebp+8) *(ebp+0xc))
26436       e9/jump $emit-subx-stmt:end/disp32
26437     }
26438     # allocate scalar
26439     {
26440       # if (!string-equal?(stmt->operation, "allocate")) break
26441       (string-equal? %ecx "allocate")  # => eax
26442       3d/compare-eax-and 0/imm32
26443       0f 84/jump-if-= break/disp32
26444       (translate-mu-allocate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
26445       e9/jump $emit-subx-stmt:end/disp32
26446     }
26447     # copy-object
26448     {
26449       # if (!string-equal?(stmt->operation, "copy-object")) break
26450       (string-equal? %ecx "copy-object")  # => eax
26451       3d/compare-eax-and 0/imm32
26452       0f 84/jump-if-= break/disp32
26453       (translate-mu-copy-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
26454       e9/jump $emit-subx-stmt:end/disp32
26455     }
26456     # clear-object
26457     {
26458       # if (!string-equal?(stmt->operation, "clear-object")) break
26459       (string-equal? %ecx "clear-object")  # => eax
26460       3d/compare-eax-and 0/imm32
26461       0f 84/jump-if-= break/disp32
26462       (translate-mu-clear-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
26463       e9/jump $emit-subx-stmt:end/disp32
26464     }
26465     # allocate array
26466     {
26467       # if (!string-equal?(stmt->operation, "populate")) break
26468       (string-equal? %ecx "populate")  # => eax
26469       3d/compare-eax-and 0/imm32
26470       0f 84/jump-if-= break/disp32
26471       (translate-mu-populate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
26472       e9/jump $emit-subx-stmt:end/disp32
26473     }
26474     # allocate stream
26475     {
26476       # if (!string-equal?(stmt->operation, "populate-stream")) break
26477       (string-equal? %ecx "populate-stream")  # => eax
26478       3d/compare-eax-and 0/imm32
26479       0f 84/jump-if-= break/disp32
26480       (translate-mu-populate-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
26481       e9/jump $emit-subx-stmt:end/disp32
26482     }
26483     # read from stream
26484     {
26485       # if (!string-equal?(stmt->operation, "read-from-stream")) break
26486       (string-equal? %ecx "read-from-stream")  # => eax
26487       3d/compare-eax-and 0/imm32
26488       0f 84/jump-if-= break/disp32
26489       (translate-mu-read-from-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
26490       e9/jump $emit-subx-stmt:end/disp32
26491     }
26492     # write to stream
26493     {
26494       # if (!string-equal?(stmt->operation, "write-to-stream")) break
26495       (string-equal? %ecx "write-to-stream")  # => eax
26496       3d/compare-eax-and 0/imm32
26497       0f 84/jump-if-= break/disp32
26498       (translate-mu-write-to-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
26499       e9/jump $emit-subx-stmt:end/disp32
26500     }
26501     # - if stmt matches a primitive, emit it
26502     {
26503 $emit-subx-stmt:check-for-primitive:
26504       # var curr/eax: (addr primitive)
26505       (find-matching-primitive *(ebp+0x10) *(ebp+0xc))  # primitives, stmt => eax
26506       3d/compare-eax-and 0/imm32
26507       74/jump-if-= break/disp8
26508 $emit-subx-stmt:primitive:
26509       (emit-subx-primitive *(ebp+8) *(ebp+0xc) %eax)  # out, stmt, curr
26510       e9/jump $emit-subx-stmt:end/disp32
26511     }
26512     # - otherwise emit a call
26513     # TODO: type-checking
26514 $emit-subx-stmt:call:
26515     (emit-call *(ebp+8) *(ebp+0xc))
26516 $emit-subx-stmt:end:
26517     # . restore registers
26518     59/pop-to-ecx
26519     58/pop-to-eax
26520     # . epilogue
26521     89/<- %esp 5/r32/ebp
26522     5d/pop-to-ebp
26523     c3/return
26524 
26525 translate-mu-length-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
26526     # . prologue
26527     55/push-ebp
26528     89/<- %ebp 4/r32/esp
26529     # . save registers
26530     50/push-eax
26531     51/push-ecx
26532     52/push-edx
26533     53/push-ebx
26534     56/push-esi
26535     # esi = stmt
26536     8b/-> *(ebp+0xc) 6/r32/esi
26537     # var base/ebx: (addr var) = stmt->inouts[0]->value
26538     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
26539     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
26540     89/<- %ebx 0/r32/eax
26541     # var elemsize/ecx: int = array-element-size(base)
26542     (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
26543     89/<- %ecx 0/r32/eax
26544     # var outreg/edx: (addr array byte) = stmt->outputs[0]->value->register
26545     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
26546     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
26547     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
26548     89/<- %edx 0/r32/eax
26549     # if elemsize == 1
26550     {
26551       81 7/subop/compare %ecx 1/imm32
26552       75/jump-if-!= break/disp8
26553 $translate-mu-length-stmt:size-1:
26554       (emit-save-size-to *(ebp+8) %ebx %edx)
26555       e9/jump $translate-mu-length-stmt:end/disp32
26556     }
26557     # if elemsize is a power of 2 less than 256
26558     {
26559       (power-of-2? %ecx *(ebp+0x10) *(ebp+0x14))  # => eax
26560       3d/compare-eax-and 0/imm32/false
26561       74/jump-if-= break/disp8
26562       81 7/subop/compare %ecx 0xff/imm32
26563       7f/jump-if-> break/disp8
26564 $translate-mu-length-stmt:size-power-of-2:
26565       (emit-save-size-to *(ebp+8) %ebx %edx)
26566       (emit-divide-by-shift-right *(ebp+8) %edx %ecx)
26567       e9/jump $translate-mu-length-stmt:end/disp32
26568     }
26569     # otherwise, the complex case
26570     # . emit register spills
26571     {
26572 $translate-mu-length-stmt:complex:
26573       (string-equal? %edx "eax")  # => eax
26574       3d/compare-eax-and 0/imm32/false
26575       75/break-if-!= break/disp8
26576       (emit-indent *(ebp+8) *Curr-block-depth)
26577       (write-buffered *(ebp+8) "50/push-eax\n")
26578     }
26579     {
26580       (string-equal? %edx "ecx")  # => eax
26581       3d/compare-eax-and 0/imm32/false
26582       75/break-if-!= break/disp8
26583       (emit-indent *(ebp+8) *Curr-block-depth)
26584       (write-buffered *(ebp+8) "51/push-ecx\n")
26585     }
26586     {
26587       (string-equal? %edx "edx")  # => eax
26588       3d/compare-eax-and 0/imm32/false
26589       75/break-if-!= break/disp8
26590       (emit-indent *(ebp+8) *Curr-block-depth)
26591       (write-buffered *(ebp+8) "52/push-edx\n")
26592     }
26593     # .
26594     (emit-save-size-to *(ebp+8) %ebx "eax")
26595     (emit-indent *(ebp+8) *Curr-block-depth)
26596     (write-buffered *(ebp+8) "31/xor %edx 2/r32/edx\n")
26597     (emit-indent *(ebp+8) *Curr-block-depth)
26598     (write-buffered *(ebp+8) "b9/copy-to-ecx ")
26599     (write-int32-hex-buffered *(ebp+8) %ecx)
26600     (write-buffered *(ebp+8) "/imm32\n")
26601     (emit-indent *(ebp+8) *Curr-block-depth)
26602     (write-buffered *(ebp+8) "f7 7/subop/idiv-eax-edx-by %ecx\n")
26603     {
26604       (string-equal? %edx "eax")  # => eax
26605       3d/compare-eax-and 0/imm32/false
26606       75/break-if-!= break/disp8
26607       (emit-indent *(ebp+8) *Curr-block-depth)
26608       (write-buffered *(ebp+8) "89/<- %")
26609       (write-buffered *(ebp+8) %edx)
26610       (write-buffered *(ebp+8) " 0/r32/eax\n")
26611     }
26612     # . emit register restores
26613     {
26614       (string-equal? %edx "edx")  # => eax
26615       3d/compare-eax-and 0/imm32/false
26616       75/break-if-!= break/disp8
26617       (emit-indent *(ebp+8) *Curr-block-depth)
26618       (write-buffered *(ebp+8) "5a/pop-to-edx\n")
26619     }
26620     {
26621       (string-equal? %edx "ecx")  # => eax
26622       3d/compare-eax-and 0/imm32/false
26623       75/break-if-!= break/disp8
26624       (emit-indent *(ebp+8) *Curr-block-depth)
26625       (write-buffered *(ebp+8) "59/pop-to-ecx\n")
26626     }
26627     {
26628       (string-equal? %edx "eax")  # => eax
26629       3d/compare-eax-and 0/imm32/false
26630       75/break-if-!= break/disp8
26631       (emit-indent *(ebp+8) *Curr-block-depth)
26632       (write-buffered *(ebp+8) "58/pop-to-eax\n")
26633     }
26634 $translate-mu-length-stmt:end:
26635     # . restore registers
26636     5e/pop-to-esi
26637     5b/pop-to-ebx
26638     5a/pop-to-edx
26639     59/pop-to-ecx
26640     58/pop-to-eax
26641     # . epilogue
26642     89/<- %esp 5/r32/ebp
26643     5d/pop-to-ebp
26644     c3/return
26645 
26646 array-element-size:  # arr: (addr var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
26647     # . prologue
26648     55/push-ebp
26649     89/<- %ebp 4/r32/esp
26650     #
26651     (array-element-type-id *(ebp+8) *(ebp+0xc) *(ebp+0x10))  # => eax
26652     (size-of-type-id-as-array-element %eax)  # => eax
26653 $array-element-size:end:
26654     # . epilogue
26655     89/<- %esp 5/r32/ebp
26656     5d/pop-to-ebp
26657     c3/return
26658 
26659 array-element-type-id:  # v: (addr var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: type-id
26660     # precondition: n is positive
26661     # . prologue
26662     55/push-ebp
26663     89/<- %ebp 4/r32/esp
26664     #
26665     8b/-> *(ebp+8) 0/r32/eax
26666     # var t/eax: (addr type-tree)
26667     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
26668     # if t == 0 abort
26669     3d/compare-eax-with 0/imm32
26670     0f 84/jump-if-== $array-element-type-id:error0/disp32
26671     # if t->is-atom? abort
26672     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
26673     0f 85/jump-if-!= $array-element-type-id:error1/disp32
26674     # if (t->left == addr) t = t->right
26675     {
26676       50/push-eax
26677       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
26678       (is-simple-mu-type? %eax 2)  # addr => eax
26679       3d/compare-eax-with 0/imm32/false
26680       58/pop-to-eax
26681       74/jump-if-= break/disp8
26682 $array-element-type-id:skip-addr:
26683       (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
26684     }
26685     # if t == 0 abort
26686     3d/compare-eax-with 0/imm32
26687     0f 84/jump-if-= $array-element-type-id:error2/disp32
26688     # if t->is-atom? abort
26689     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
26690     0f 85/jump-if-!= $array-element-type-id:error2/disp32
26691     # if t->left != array abort
26692     {
26693       50/push-eax
26694       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
26695       (is-simple-mu-type? %eax 3)  # array => eax
26696       3d/compare-eax-with 0/imm32/false
26697       58/pop-to-eax
26698 $array-element-type-id:no-array:
26699       0f 84/jump-if-= $array-element-type-id:error2/disp32
26700     }
26701 $array-element-type-id:skip-array:
26702     # t = t->right
26703     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
26704     # if t == 0 abort
26705     3d/compare-eax-with 0/imm32
26706     0f 84/jump-if-= $array-element-type-id:error2/disp32
26707     # if t->is-atom? abort
26708     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
26709     0f 85/jump-if-!= $array-element-type-id:error2/disp32
26710     # t = t->left
26711     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
26712     # if (!t->is-atom?) t = t->left     # TODO: assumes array element size can be determined from just first word of array element type
26713     # if (t->is-atom == false) t = lookup(t->left)
26714     {
26715       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
26716       75/jump-if-!= break/disp8
26717       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
26718     }
26719     # return t->value
26720     8b/-> *(eax+4) 0/r32/eax  # Type-tree-value
26721 $array-element-type-id:end:
26722     # . epilogue
26723     89/<- %esp 5/r32/ebp
26724     5d/pop-to-ebp
26725     c3/return
26726 
26727 $array-element-type-id:error0:
26728     (write-buffered *(ebp+0xc) "array-element-type-id: var '")
26729     50/push-eax
26730     8b/-> *(ebp+8) 0/r32/eax
26731     (lookup *eax *(eax+4))  # Var-name Var-name => eax
26732     (write-buffered *(ebp+0xc) %eax)
26733     58/pop-to-eax
26734     (write-buffered *(ebp+0xc) "' has no type\n")
26735     (flush *(ebp+0xc))
26736     (stop *(ebp+0x10) 1)
26737     # never gets here
26738 
26739 $array-element-type-id:error1:
26740     (write-buffered *(ebp+0xc) "array-element-type-id: var '")
26741     50/push-eax
26742     8b/-> *(ebp+8) 0/r32/eax
26743     (lookup *eax *(eax+4))  # Var-name Var-name => eax
26744     (write-buffered *(ebp+0xc) %eax)
26745     58/pop-to-eax
26746     (write-buffered *(ebp+0xc) "' has atomic type ")
26747     (write-int32-hex-buffered *(ebp+0xc) *(eax+4))  # Type-tree-value
26748     (write-buffered *(ebp+0xc) Newline)
26749     (flush *(ebp+0xc))
26750     (stop *(ebp+0x10) 1)
26751     # never gets here
26752 
26753 $array-element-type-id:error2:
26754     (write-buffered *(ebp+0xc) "array-element-type-id: var '")
26755     50/push-eax
26756     8b/-> *(ebp+8) 0/r32/eax
26757     (lookup *eax *(eax+4))  # Var-name Var-name => eax
26758     (write-buffered *(ebp+0xc) %eax)
26759     58/pop-to-eax
26760     (write-buffered *(ebp+0xc) "' has non-array type\n")
26761     (flush *(ebp+0xc))
26762     (stop *(ebp+0x10) 1)
26763     # never gets here
26764 
26765 size-of-type-id-as-array-element:  # t: type-id -> result/eax: int
26766     # . prologue
26767     55/push-ebp
26768     89/<- %ebp 4/r32/esp
26769     # eax = t
26770     8b/-> *(ebp+8) 0/r32/eax
26771     # if t is 'byte', size is 1
26772     3d/compare-eax-and 8/imm32/byte
26773     {
26774       75/jump-if-!= break/disp8
26775       b8/copy-to-eax 1/imm32
26776       eb/jump $size-of-type-id-as-array-element:end/disp8
26777     }
26778     # otherwise proceed as usual
26779     (size-of-type-id %eax)  # => eax
26780 $size-of-type-id-as-array-element:end:
26781     # . epilogue
26782     89/<- %esp 5/r32/ebp
26783     5d/pop-to-ebp
26784     c3/return
26785 
26786 emit-save-size-to:  # out: (addr buffered-file), base: (addr var), outreg: (addr array byte)
26787     # . prologue
26788     55/push-ebp
26789     89/<- %ebp 4/r32/esp
26790     # . save registers
26791     50/push-eax
26792     53/push-ebx
26793     # ebx = base
26794     8b/-> *(ebp+0xc) 3/r32/ebx
26795     (emit-indent *(ebp+8) *Curr-block-depth)
26796     (write-buffered *(ebp+8) "8b/-> *")
26797     # if base is an (addr array ...) in a register
26798     {
26799       81 7/subop/compare *(ebx+0x18)) 0/imm32  # Var-register
26800       74/jump-if-= break/disp8
26801 $emit-save-size-to:emit-base-from-register:
26802       (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
26803       (write-buffered *(ebp+8) %eax)
26804       eb/jump $emit-save-size-to:emit-output/disp8
26805     }
26806     # otherwise if base is an (array ...) on the stack
26807     {
26808       81 7/subop/compare *(ebx+0x14)) 0/imm32  # Var-offset
26809       74/jump-if-= break/disp8
26810 $emit-save-size-to:emit-base-from-stack:
26811       (write-buffered *(ebp+8) "(ebp+")
26812       (write-int32-hex-buffered *(ebp+8) *(ebx+0x14))  # Var-offset
26813       (write-buffered *(ebp+8) ")")
26814     }
26815 $emit-save-size-to:emit-output:
26816     (write-buffered *(ebp+8) " ")
26817     (get Mu-registers *(ebp+0x10) 0xc "Mu-registers")  # => eax
26818     (write-int32-hex-buffered *(ebp+8) *eax)
26819     (write-buffered *(ebp+8) "/r32\n")
26820 $emit-save-size-to:end:
26821     # . restore registers
26822     5b/pop-to-ebx
26823     58/pop-to-eax
26824     # . epilogue
26825     89/<- %esp 5/r32/ebp
26826     5d/pop-to-ebp
26827     c3/return
26828 
26829 emit-divide-by-shift-right:  # out: (addr buffered-file), reg: (addr array byte), size: int
26830     # . prologue
26831     55/push-ebp
26832     89/<- %ebp 4/r32/esp
26833     # . save registers
26834     50/push-eax
26835     #
26836     (emit-indent *(ebp+8) *Curr-block-depth)
26837     (write-buffered *(ebp+8) "c1/shift 5/subop/>> %")
26838     (write-buffered *(ebp+8) *(ebp+0xc))
26839     (write-buffered *(ebp+8) Space)
26840     (num-shift-rights *(ebp+0x10))  # => eax
26841     (write-int32-hex-buffered *(ebp+8) %eax)
26842     (write-buffered *(ebp+8) "/imm8\n")
26843 $emit-divide-by-shift-right:end:
26844     # . restore registers
26845     58/pop-to-eax
26846     # . epilogue
26847     89/<- %esp 5/r32/ebp
26848     5d/pop-to-ebp
26849     c3/return
26850 
26851 # a little different from other translate- functions; notice the extra 'fn' argument
26852 translate-mu-index-stmt:  # out: (addr buffered-file), stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
26853     # . prologue
26854     55/push-ebp
26855     89/<- %ebp 4/r32/esp
26856     # . save registers
26857     53/push-ebx
26858     # ebx = stmt
26859     8b/-> *(ebp+0xc) 3/r32/ebx
26860     # var base/ebx: (addr var) = stmt->inouts[0]
26861     (lookup *(ebx+0xc) *(ebx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
26862     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
26863     89/<- %ebx 0/r32/eax
26864     # emit bounds-check
26865     (emit-mu-index-bounds-check *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18))
26866     # if (var->register) do one thing
26867     {
26868       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
26869       74/jump-if-= break/disp8
26870       # TODO: ensure there's no dereference
26871       (translate-mu-index-stmt-with-array-in-register *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
26872       eb/jump $translate-mu-index-stmt:end/disp8
26873     }
26874     # if (var->offset) do a different thing
26875     {
26876       81 7/subop/compare *(ebx+0x14) 0/imm32  # Var-offset
26877       74/jump-if-= break/disp8
26878       # TODO: ensure there's no dereference
26879       (translate-mu-index-stmt-with-array-on-stack *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
26880       eb/jump $translate-mu-index-stmt:end/disp8
26881     }
26882 $translate-mu-index-stmt:end:
26883     # . restore registers
26884     5b/pop-to-ebx
26885     # . epilogue
26886     89/<- %esp 5/r32/ebp
26887     5d/pop-to-ebp
26888     c3/return
26889 
26890 $translate-mu-index-stmt:error1:
26891     (write-buffered *(ebp+0x14) "couldn't translate an index instruction. second (index) input must either lie in a register or be a literal\n")
26892     (flush *(ebp+0x14))
26893     (stop *(ebp+0x18) 1)
26894     # never gets here
26895 
26896 $translate-mu-index-stmt:error2:
26897     (write-buffered *(ebp+0x14) "couldn't translate an index instruction. second (index) input when in a register must be an int or offset\n")
26898     (flush *(ebp+0x14))
26899     (stop *(ebp+0x18) 1)
26900     # never gets here
26901 
26902 emit-mu-index-bounds-check:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
26903     # . prologue
26904     55/push-ebp
26905     89/<- %ebp 4/r32/esp
26906     # . save registers
26907     50/push-eax
26908     51/push-ecx
26909     52/push-edx
26910     53/push-ebx
26911     # ecx = stmt
26912     8b/-> *(ebp+0xc) 1/r32/ecx
26913     #
26914     (emit-indent *(ebp+8) *Curr-block-depth)
26915     (write-buffered *(ebp+8) "(__check-mu-array-bounds ")
26916 $emit-mu-index-bounds-check:compute-base:
26917     # var base/ebx: (addr var) = inouts[0]
26918     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
26919     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
26920     89/<- %ebx 0/r32/eax
26921 $emit-mu-index-bounds-check:emit-index:
26922     # var index/edx: (addr var) = inouts[1]
26923     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
26924     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
26925     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
26926     89/<- %edx 0/r32/eax
26927     # if index->register, print its code
26928     81 7/subop/compare *(edx+0x18) 0/imm32  # Var-register
26929     {
26930       0f 84/jump-if-= break/disp32
26931 $emit-mu-index-bounds-check:emit-register-index:
26932       (write-buffered *(ebp+8) "%")
26933       (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
26934       (write-buffered *(ebp+8) %eax)
26935       eb/jump $emit-mu-index-bounds-check:index-done/disp8
26936     }
26937     # otherwise if index is a literal, print it
26938 $emit-mu-index-bounds-check:emit-literal-index:
26939     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
26940     (is-simple-mu-type? %eax 0)  # => eax
26941     3d/compare-eax-and 0/imm32/false
26942     {
26943       0f 84/jump-if-= break/disp32
26944       (lookup *edx *(edx+4))  # Var-name Var-name => eax
26945       (write-buffered *(ebp+8) %eax)
26946     }
26947 $emit-mu-index-bounds-check:index-done:
26948     (write-buffered *(ebp+8) " ")
26949 $emit-mu-index-bounds-check:emit-element-size:
26950     # if index is a literal or int, print size of array element
26951     {
26952       {
26953         (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
26954         (is-simple-mu-type? %eax 0)  # literal => eax
26955         3d/compare-eax-and 0/imm32/false
26956         75/jump-if-!= break/disp8
26957         (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
26958         (is-simple-mu-type? %eax 1)  # int => eax
26959         3d/compare-eax-and 0/imm32/false
26960         75/jump-if-!= break/disp8
26961         eb/jump $emit-mu-index-bounds-check:emit-element-size-offset/disp8
26962       }
26963 $emit-mu-index-bounds-check:emit-int-register-index:
26964       (array-element-size %ebx *(ebp+0x14) *(ebp+0x18))  # => eax
26965       (write-int32-hex-buffered *(ebp+8) %eax)
26966       e9/jump $emit-mu-index-bounds-check:emit-base/disp32
26967     }
26968 $emit-mu-index-bounds-check:emit-element-size-offset:
26969     # if index has type (offset ...), print "1"
26970     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
26971     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
26972     {
26973       75/jump-if-!= break/disp8
26974       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
26975       (is-simple-mu-type? %eax 7)  # => eax
26976       3d/compare-eax-and 0/imm32/false
26977       {
26978         0f 84/jump-if-= break/disp32
26979 $emit-mu-index-bounds-check:emit-offset-register-index:
26980         (write-buffered *(ebp+8) "1")
26981       }
26982     }
26983 $emit-mu-index-bounds-check:emit-base:
26984     # if base is in a register, print " *" base->register
26985     81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
26986     {
26987       74/jump-if-= break/disp8
26988       (write-buffered *(ebp+8) " *")
26989       (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
26990       (write-buffered *(ebp+8) %eax)
26991       e9/jump $emit-mu-index-bounds-check:emit-function-name/disp32
26992     }
26993     # otherwise print " *(ebp+" base->offset ")"
26994     (write-buffered *(ebp+8) " *(ebp+")
26995     (write-int32-hex-buffered *(ebp+8) *(ebx+0x14))  # Var-offset
26996     (write-buffered *(ebp+8) ")")
26997 $emit-mu-index-bounds-check:emit-function-name:
26998     # " \"" function-name "\""
26999     (write-buffered *(ebp+8) " \"")
27000     8b/-> *(ebp+0x10) 1/r32/ecx
27001     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
27002     (write-buffered *(ebp+8) %eax)
27003     (write-buffered *(ebp+8) "\"")
27004 $emit-mu-index-bounds-check:emit-array-name:
27005     # " \"" base->name "\""
27006     (write-buffered *(ebp+8) " \"")
27007     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
27008     (write-buffered *(ebp+8) %eax)
27009     (write-buffered *(ebp+8) "\")\n")
27010 $emit-mu-index-bounds-check:end:
27011     # . restore registers
27012     5b/pop-to-ebx
27013     5a/pop-to-edx
27014     59/pop-to-ecx
27015     58/pop-to-eax
27016     # . epilogue
27017     89/<- %esp 5/r32/ebp
27018     5d/pop-to-ebp
27019     c3/return
27020 
27021 translate-mu-index-stmt-with-array-in-register:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
27022     # . prologue
27023     55/push-ebp
27024     89/<- %ebp 4/r32/esp
27025     # . save registers
27026     50/push-eax
27027     51/push-ecx
27028     52/push-edx
27029     53/push-ebx
27030     #
27031     (emit-indent *(ebp+8) *Curr-block-depth)
27032     (write-buffered *(ebp+8) "8d/copy-address *(")
27033     # TODO: ensure inouts[0] is in a register and not dereferenced
27034 $translate-mu-index-stmt-with-array-in-register:emit-base:
27035     # ecx = stmt
27036     8b/-> *(ebp+0xc) 1/r32/ecx
27037     # var base/ebx: (addr var) = inouts[0]
27038     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
27039     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
27040     89/<- %ebx 0/r32/eax
27041     # print base->register " + "
27042     (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
27043     (write-buffered *(ebp+8) %eax)
27044     (write-buffered *(ebp+8) " + ")
27045     # var index/edx: (addr var) = inouts[1]
27046     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
27047     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
27048     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
27049     89/<- %edx 0/r32/eax
27050     # if index->register
27051     81 7/subop/compare *(edx+0x18) 0/imm32  # Var-register
27052     {
27053       0f 84/jump-if-= break/disp32
27054 $translate-mu-index-stmt-with-array-in-register:emit-register-index:
27055       # if index is an int
27056       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
27057       (is-simple-mu-type? %eax 1)  # int => eax
27058       3d/compare-eax-and 0/imm32/false
27059       {
27060         0f 84/jump-if-= break/disp32
27061 $translate-mu-index-stmt-with-array-in-register:emit-int-register-index:
27062         # print index->register "<<" log2(array-element-size(base)) " + 4) "
27063         # . index->register "<<"
27064         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
27065         (write-buffered *(ebp+8) %eax)
27066         (write-buffered *(ebp+8) "<<")
27067         # . log2(array-element-size(base->type))
27068         # we know size is a power of 2
27069         (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
27070         (num-shift-rights %eax)  # => eax
27071         (write-int32-hex-buffered *(ebp+8) %eax)
27072         e9/jump $translate-mu-index-stmt-with-array-in-register:emit-register-index-done/disp32
27073       }
27074       # if index->type is any other atom, abort
27075       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
27076       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
27077       0f 85/jump-if-!= $translate-mu-index-stmt:error2/disp32
27078       # if index has type (offset ...)
27079       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
27080       (is-simple-mu-type? %eax 7)  # => eax
27081       3d/compare-eax-and 0/imm32/false
27082       {
27083         0f 84/jump-if-= break/disp32
27084         # print index->register
27085 $translate-mu-index-stmt-with-array-in-register:emit-offset-register-index:
27086         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
27087         (write-buffered *(ebp+8) %eax)
27088       }
27089 $translate-mu-index-stmt-with-array-in-register:emit-register-index-done:
27090       (write-buffered *(ebp+8) " + 4) ")
27091       e9/jump $translate-mu-index-stmt-with-array-in-register:emit-output/disp32
27092     }
27093     # otherwise if index is a literal
27094     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
27095     (is-simple-mu-type? %eax 0)  # => eax
27096     3d/compare-eax-and 0/imm32/false
27097     {
27098       0f 84/jump-if-= break/disp32
27099 $translate-mu-index-stmt-with-array-in-register:emit-literal-index:
27100       # var index-value/edx: int = parse-hex-int(index->name)
27101       (lookup *edx *(edx+4))  # Var-name Var-name => eax
27102       (parse-hex-int %eax)  # => eax
27103       89/<- %edx 0/r32/eax
27104       # offset = idx-value * array-element-size(base->type)
27105       (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
27106       f7 4/subop/multiply-into-edx-eax %edx  # clobbers edx
27107       # offset += 4 for array size
27108       05/add-to-eax 4/imm32
27109       # TODO: check edx for overflow
27110       # print offset
27111       (write-int32-hex-buffered *(ebp+8) %eax)
27112       (write-buffered *(ebp+8) ") ")
27113       e9/jump $translate-mu-index-stmt-with-array-in-register:emit-output/disp32
27114     }
27115     # otherwise abort
27116     e9/jump $translate-mu-index-stmt:error1/disp32
27117 $translate-mu-index-stmt-with-array-in-register:emit-output:
27118     # outputs[0] "/r32"
27119     8b/-> *(ebp+0xc) 1/r32/ecx
27120     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
27121     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
27122     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
27123     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
27124     (write-int32-hex-buffered *(ebp+8) *eax)
27125     (write-buffered *(ebp+8) "/r32\n")
27126 $translate-mu-index-stmt-with-array-in-register:end:
27127     # . restore registers
27128     5b/pop-to-ebx
27129     5a/pop-to-edx
27130     59/pop-to-ecx
27131     58/pop-to-eax
27132     # . epilogue
27133     89/<- %esp 5/r32/ebp
27134     5d/pop-to-ebp
27135     c3/return
27136 
27137 translate-mu-index-stmt-with-array-on-stack:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
27138     # . prologue
27139     55/push-ebp
27140     89/<- %ebp 4/r32/esp
27141     # . save registers
27142     50/push-eax
27143     51/push-ecx
27144     52/push-edx
27145     53/push-ebx
27146     #
27147     (emit-indent *(ebp+8) *Curr-block-depth)
27148     (write-buffered *(ebp+8) "8d/copy-address *(ebp + ")
27149     # var curr/edx: (addr stmt-var) = lookup(stmt->inouts)
27150     8b/-> *(ebp+0xc) 0/r32/eax
27151     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
27152     89/<- %edx 0/r32/eax
27153     # var base/ecx: (addr var) = lookup(curr->value)
27154     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
27155     89/<- %ecx 0/r32/eax
27156     # var curr2/eax: (addr stmt-var) = lookup(curr->next)
27157     (lookup *(edx+8) *(edx+0xc))  # Stmt-var-next Stmt-var-next => eax
27158     # var index/edx: (handle var) = curr2->value
27159     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
27160     89/<- %edx 0/r32/eax
27161     # if index->register
27162     81 7/subop/compare *(edx+0x18) 0/imm32  # Var-register
27163     {
27164       0f 84/jump-if-= break/disp32
27165 $translate-mu-index-stmt-with-array-on-stack:emit-register-index:
27166       # if index is an int
27167       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
27168       (is-simple-mu-type? %eax 1)  # int => eax
27169       3d/compare-eax-and 0/imm32/false
27170       {
27171         0f 84/jump-if-= break/disp32
27172 $translate-mu-index-stmt-with-array-on-stack:emit-int-register-index:
27173         # print index->register "<<" log2(array-element-size(base)) " + " base->offset+4
27174         # . inouts[1]->register "<<"
27175         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
27176         (write-buffered *(ebp+8) %eax)
27177         (write-buffered *(ebp+8) "<<")
27178         # . log2(array-element-size(base))
27179         # TODO: ensure size is a power of 2
27180         (array-element-size %ecx *(ebp+0x10) *(ebp+0x14))  # => eax
27181         (num-shift-rights %eax)  # => eax
27182         (write-int32-hex-buffered *(ebp+8) %eax)
27183         #
27184         (write-buffered *(ebp+8) " + ")
27185         #
27186         8b/-> *(ecx+0x14) 0/r32/eax  # Var-offset
27187         05/add-to-eax 4/imm32  # for array length
27188         (write-int32-hex-buffered *(ebp+8) %eax)
27189         e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-register-index-done/disp32
27190       }
27191       # if index->type is any other atom, abort
27192       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
27193       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
27194       0f 85/jump-if-!= $translate-mu-index-stmt:error2/disp32
27195       # if index has type (offset ...)
27196       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
27197       (is-simple-mu-type? %eax 7)  # => eax
27198       3d/compare-eax-and 0/imm32/false
27199       {
27200         0f 84/jump-if-= break/disp32
27201         # print index->register
27202 $translate-mu-index-stmt-with-array-on-stack:emit-offset-register-index:
27203         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
27204         (write-buffered *(ebp+8) %eax)
27205       }
27206 $translate-mu-index-stmt-with-array-on-stack:emit-register-index-done:
27207       (write-buffered *(ebp+8) ") ")
27208       e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-output/disp32
27209     }
27210     # otherwise if index is a literal
27211     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
27212     (is-simple-mu-type? %eax 0)  # => eax
27213     3d/compare-eax-and 0/imm32/false
27214     {
27215       0f 84/jump-if-= break/disp32
27216 $translate-mu-index-stmt-with-array-on-stack:emit-literal-index:
27217       # var idx-value/edx: int = parse-hex-int(index->name)
27218       (lookup *edx *(edx+4))  # Var-name Var-name => eax
27219       (parse-hex-int %eax)  # Var-name => eax
27220       89/<- %edx 0/r32/eax
27221       # offset = idx-value * array-element-size(base)
27222       (array-element-size %ecx *(ebp+0x10) *(ebp+0x14))  # => eax
27223       f7 4/subop/multiply-into-edx-eax %edx  # clobbers edx
27224       # offset += base->offset
27225       03/add *(ecx+0x14) 0/r32/eax  # Var-offset
27226       # offset += 4 for array size
27227       05/add-to-eax 4/imm32
27228       # TODO: check edx for overflow
27229       # print offset
27230       (write-int32-hex-buffered *(ebp+8) %eax)
27231       (write-buffered *(ebp+8) ") ")
27232       e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-output/disp32
27233     }
27234     # otherwise abort
27235     e9/jump $translate-mu-index-stmt:error1/disp32
27236 $translate-mu-index-stmt-with-array-on-stack:emit-output:
27237     # outputs[0] "/r32"
27238     8b/-> *(ebp+0xc) 0/r32/eax
27239     (lookup *(eax+0x14) *(eax+0x18))  # Stmt1-outputs Stmt1-outputs => eax
27240     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
27241     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
27242     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
27243     (write-int32-hex-buffered *(ebp+8) *eax)
27244     (write-buffered *(ebp+8) "/r32\n")
27245 $translate-mu-index-stmt-with-array-on-stack:end:
27246     # . restore registers
27247     5b/pop-to-ebx
27248     5a/pop-to-edx
27249     59/pop-to-ecx
27250     58/pop-to-eax
27251     # . epilogue
27252     89/<- %esp 5/r32/ebp
27253     5d/pop-to-ebp
27254     c3/return
27255 
27256 translate-mu-compute-index-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
27257     # . prologue
27258     55/push-ebp
27259     89/<- %ebp 4/r32/esp
27260     # . save registers
27261     50/push-eax
27262     51/push-ecx
27263     52/push-edx
27264     53/push-ebx
27265     #
27266     (emit-indent *(ebp+8) *Curr-block-depth)
27267     (write-buffered *(ebp+8) "69/multiply")
27268     # ecx = stmt
27269     8b/-> *(ebp+0xc) 1/r32/ecx
27270     # var first-inout/ebx: (addr stmt-var) = stmt->inouts[0]
27271     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
27272     89/<- %ebx 0/r32/eax
27273 $translate-mu-compute-index-stmt:emit-index:
27274     (lookup *(ebx+8) *(ebx+0xc))  # Stmt-var-next Stmt-var-next => eax
27275     (emit-subx-var-as-rm32 *(ebp+8) %eax)
27276     (write-buffered *(ebp+8) Space)
27277 $translate-mu-compute-index-stmt:emit-elem-size:
27278     # var base/ebx: (addr var)
27279     (lookup *ebx *(ebx+4))  # Stmt-var-value Stmt-var-value => eax
27280     89/<- %ebx 0/r32/eax
27281     # print array-element-size(base)
27282     (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
27283     (write-int32-hex-buffered *(ebp+8) %eax)
27284     (write-buffered *(ebp+8) "/imm32 ")
27285 $translate-mu-compute-index-stmt:emit-output:
27286     # outputs[0] "/r32"
27287     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
27288     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
27289     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
27290     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
27291     (write-int32-hex-buffered *(ebp+8) *eax)
27292     (write-buffered *(ebp+8) "/r32\n")
27293 $translate-mu-compute-index-stmt:end:
27294     # . restore registers
27295     5b/pop-to-ebx
27296     5a/pop-to-edx
27297     59/pop-to-ecx
27298     58/pop-to-eax
27299     # . epilogue
27300     89/<- %esp 5/r32/ebp
27301     5d/pop-to-ebp
27302     c3/return
27303 
27304 translate-mu-get-stmt:  # out: (addr buffered-file), stmt: (addr stmt)
27305     # . prologue
27306     55/push-ebp
27307     89/<- %ebp 4/r32/esp
27308     # . save registers
27309     50/push-eax
27310     51/push-ecx
27311     52/push-edx
27312     #
27313     (emit-indent *(ebp+8) *Curr-block-depth)
27314     (write-buffered *(ebp+8) "8d/copy-address ")
27315     # ecx = stmt
27316     8b/-> *(ebp+0xc) 1/r32/ecx
27317     # var offset/edx: int = get offset of stmt
27318     (mu-get-offset %ecx)  # => eax
27319     89/<- %edx 0/r32/eax
27320     # var base/eax: (addr var) = stmt->inouts->value
27321     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
27322     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
27323     # if base is in a register
27324     81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
27325     {
27326       0f 84/jump-if-= break/disp32
27327 $translate-mu-get-stmt:emit-register-input:
27328       # emit "*(" base->register " + " offset ") "
27329       (write-buffered *(ebp+8) "*(")
27330       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
27331       (write-buffered *(ebp+8) %eax)
27332       (write-buffered *(ebp+8) " + ")
27333       (write-int32-hex-buffered *(ebp+8) %edx)
27334       (write-buffered *(ebp+8) ") ")
27335       e9/jump $translate-mu-get-stmt:emit-output/disp32
27336     }
27337     # otherwise base is on the stack
27338     {
27339 $translate-mu-get-stmt:emit-stack-input:
27340       # emit "*(ebp + " inouts[0]->stack-offset + offset ") "
27341       (write-buffered *(ebp+8) "*(ebp+")
27342       03/add *(eax+0x14) 2/r32/edx  # Var-offset
27343       (write-int32-hex-buffered *(ebp+8) %edx)
27344       (write-buffered *(ebp+8) ") ")
27345       eb/jump $translate-mu-get-stmt:emit-output/disp8
27346     }
27347 $translate-mu-get-stmt:emit-output:
27348     # var output/eax: (addr var) = stmt->outputs->value
27349     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
27350     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
27351     # emit offset->register "/r32"
27352     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
27353     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
27354     (write-int32-hex-buffered *(ebp+8) *eax)
27355     (write-buffered *(ebp+8) "/r32\n")
27356 $translate-mu-get-stmt:end:
27357     # . restore registers
27358     5a/pop-to-edx
27359     59/pop-to-ecx
27360     58/pop-to-eax
27361     # . epilogue
27362     89/<- %esp 5/r32/ebp
27363     5d/pop-to-ebp
27364     c3/return
27365 
27366 translate-mu-copy-object-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
27367     # . prologue
27368     55/push-ebp
27369     89/<- %ebp 4/r32/esp
27370     # . save registers
27371     50/push-eax
27372     #
27373     (emit-indent *(ebp+8) *Curr-block-depth)
27374     (write-buffered *(ebp+8) "(copy-bytes")
27375     # eax = stmt
27376     8b/-> *(ebp+0xc) 0/r32/eax
27377     # var first-inout/eax: (addr stmt-var) = stmt->inouts[0]
27378     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
27379     (emit-subx-call-operand *(ebp+8) %eax)
27380     # var second-inout/eax: (addr stmt-var) = stmt->inouts[1]
27381     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
27382     (emit-subx-call-operand *(ebp+8) %eax)
27383     # emit size of inouts
27384     (write-buffered *(ebp+8) Space)
27385     (addr-payload-size %eax *(ebp+0x10) *(ebp+0x14))  # => eax
27386     (write-int32-hex-buffered *(ebp+8) %eax)
27387     (write-buffered *(ebp+8) ")\n")
27388 $translate-mu-copy-object-stmt:end:
27389     # . restore registers
27390     58/pop-to-eax
27391     # . epilogue
27392     89/<- %esp 5/r32/ebp
27393     5d/pop-to-ebp
27394     c3/return
27395 
27396 translate-mu-clear-object-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
27397     # . prologue
27398     55/push-ebp
27399     89/<- %ebp 4/r32/esp
27400     # . save registers
27401     50/push-eax
27402     #
27403     (emit-indent *(ebp+8) *Curr-block-depth)
27404     (write-buffered *(ebp+8) "(zero-out")
27405     # eax = stmt
27406     8b/-> *(ebp+0xc) 0/r32/eax
27407     # var dest/eax: (addr stmt-var) = stmt->inouts[0]
27408     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
27409     #
27410     (emit-subx-call-operand *(ebp+8) %eax)
27411     (write-buffered *(ebp+8) Space)
27412     (addr-payload-size %eax *(ebp+0x10) *(ebp+0x14))  # => eax
27413     (write-int32-hex-buffered *(ebp+8) %eax)
27414     (write-buffered *(ebp+8) ")\n")
27415 $translate-mu-clear-object-stmt:end:
27416     # . restore registers
27417     58/pop-to-eax
27418     # . epilogue
27419     89/<- %esp 5/r32/ebp
27420     5d/pop-to-ebp
27421     c3/return
27422 
27423 translate-mu-allocate-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
27424     # . prologue
27425     55/push-ebp
27426     89/<- %ebp 4/r32/esp
27427     # . save registers
27428     50/push-eax
27429     56/push-esi
27430     57/push-edi
27431     # esi = stmt
27432     8b/-> *(ebp+0xc) 6/r32/esi
27433     # var target/edi: (addr stmt-var) = stmt->inouts[0]
27434     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
27435     89/<- %edi 0/r32/eax
27436     #
27437     (emit-indent *(ebp+8) *Curr-block-depth)
27438     (write-buffered *(ebp+8) "(allocate Heap ")
27439     (addr-handle-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
27440     (write-int32-hex-buffered *(ebp+8) %eax)
27441     (emit-subx-call-operand *(ebp+8) %edi)
27442     (write-buffered *(ebp+8) ")\n")
27443 $translate-mu-allocate-stmt:end:
27444     # . restore registers
27445     5f/pop-to-edi
27446     5e/pop-to-esi
27447     58/pop-to-eax
27448     # . epilogue
27449     89/<- %esp 5/r32/ebp
27450     5d/pop-to-ebp
27451     c3/return
27452 
27453 addr-handle-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
27454     # . prologue
27455     55/push-ebp
27456     89/<- %ebp 4/r32/esp
27457     # var t/eax: (addr type-tree) = s->value->type
27458     8b/-> *(ebp+8) 0/r32/eax
27459     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
27460     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
27461     # TODO: check eax != 0
27462     # TODO: check !t->is-atom?
27463     # TODO: check t->left == addr
27464     # t = t->right
27465 $addr-handle-payload-size:skip-addr:
27466     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
27467     # TODO: check eax != 0
27468     # TODO: check !t->is-atom?
27469     # TODO: check t->left == handle
27470     # t = t->right
27471 $addr-handle-payload-size:skip-handle:
27472     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
27473     # TODO: check eax != 0
27474     # if !t->is-atom? t = t->left
27475     81 7/subop/compare *eax 0/imm32/false
27476     {
27477       75/jump-if-!= break/disp8
27478       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
27479     }
27480     # TODO: check t->is-atom?
27481     # return size(t->value)
27482     (size-of-type-id *(eax+4))  # Type-tree-value => eax
27483 $addr-handle-payload-size:end:
27484     # . epilogue
27485     89/<- %esp 5/r32/ebp
27486     5d/pop-to-ebp
27487     c3/return
27488 
27489 addr-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
27490     # . prologue
27491     55/push-ebp
27492     89/<- %ebp 4/r32/esp
27493     # var t/eax: (addr type-tree) = s->value->type
27494     8b/-> *(ebp+8) 0/r32/eax
27495     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
27496     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
27497     # TODO: check eax != 0
27498     # TODO: check !t->is-atom?
27499     # TODO: check t->left == addr
27500     # t = t->right
27501 $addr-payload-size:skip-addr:
27502     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
27503     # TODO: check eax != 0
27504     # if !t->is-atom? t = t->left
27505     81 7/subop/compare *eax 0/imm32/false
27506     {
27507       75/jump-if-!= break/disp8
27508       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
27509     }
27510     # TODO: check t->is-atom?
27511     # return size(t->value)
27512     (size-of-type-id *(eax+4))  # Type-tree-value => eax
27513 $addr-payload-size:end:
27514     # . epilogue
27515     89/<- %esp 5/r32/ebp
27516     5d/pop-to-ebp
27517     c3/return
27518 
27519 translate-mu-populate-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
27520     # . prologue
27521     55/push-ebp
27522     89/<- %ebp 4/r32/esp
27523     # . save registers
27524     50/push-eax
27525     51/push-ecx
27526     56/push-esi
27527     57/push-edi
27528     # esi = stmt
27529     8b/-> *(ebp+0xc) 6/r32/esi
27530     # var target/edi: (addr stmt-var) = stmt->inouts[0]
27531     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
27532     89/<- %edi 0/r32/eax
27533     # var len/ecx: (addr stmt-var) = stmt->inouts[1]
27534     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
27535     89/<- %ecx 0/r32/eax
27536     #
27537     (emit-indent *(ebp+8) *Curr-block-depth)
27538     (write-buffered *(ebp+8) "(allocate-array2 Heap ")
27539     (addr-handle-array-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
27540     (write-int32-hex-buffered *(ebp+8) %eax)
27541     (emit-subx-call-operand *(ebp+8) %ecx)
27542     (emit-subx-call-operand *(ebp+8) %edi)
27543     (write-buffered *(ebp+8) ")\n")
27544 $translate-mu-populate-stmt:end:
27545     # . restore registers
27546     5f/pop-to-edi
27547     5e/pop-to-esi
27548     59/pop-to-ecx
27549     58/pop-to-eax
27550     # . epilogue
27551     89/<- %esp 5/r32/ebp
27552     5d/pop-to-ebp
27553     c3/return
27554 
27555 translate-mu-populate-stream-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
27556     # . prologue
27557     55/push-ebp
27558     89/<- %ebp 4/r32/esp
27559     # . save registers
27560     50/push-eax
27561     51/push-ecx
27562     56/push-esi
27563     57/push-edi
27564     # esi = stmt
27565     8b/-> *(ebp+0xc) 6/r32/esi
27566     # var target/edi: (addr stmt-var) = stmt->inouts[0]
27567     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
27568     89/<- %edi 0/r32/eax
27569     # var len/ecx: (addr stmt-var) = stmt->inouts[1]
27570     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
27571     89/<- %ecx 0/r32/eax
27572     #
27573     (emit-indent *(ebp+8) *Curr-block-depth)
27574     (write-buffered *(ebp+8) "(new-stream Heap ")
27575     (addr-handle-stream-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
27576     (write-int32-hex-buffered *(ebp+8) %eax)
27577     (emit-subx-call-operand *(ebp+8) %ecx)
27578     (emit-subx-call-operand *(ebp+8) %edi)
27579     (write-buffered *(ebp+8) ")\n")
27580 $translate-mu-populate-stream-stmt:end:
27581     # . restore registers
27582     5f/pop-to-edi
27583     5e/pop-to-esi
27584     59/pop-to-ecx
27585     58/pop-to-eax
27586     # . epilogue
27587     89/<- %esp 5/r32/ebp
27588     5d/pop-to-ebp
27589     c3/return
27590 
27591 translate-mu-read-from-stream-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
27592     # . prologue
27593     55/push-ebp
27594     89/<- %ebp 4/r32/esp
27595     # . save registers
27596     50/push-eax
27597     51/push-ecx
27598     56/push-esi
27599     57/push-edi
27600     # esi = stmt
27601     8b/-> *(ebp+0xc) 6/r32/esi
27602     # var stream/ecx: (addr stmt-var) = stmt->inouts[0]
27603     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
27604     89/<- %ecx 0/r32/eax
27605     # var target/edi: (addr stmt-var) = stmt->inouts[1]
27606     (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
27607     89/<- %edi 0/r32/eax
27608     #
27609     (emit-indent *(ebp+8) *Curr-block-depth)
27610     (write-buffered *(ebp+8) "(read-from-stream")
27611     (emit-subx-call-operand *(ebp+8) %ecx)
27612     (emit-subx-call-operand *(ebp+8) %edi)
27613     (write-buffered *(ebp+8) Space)
27614     (addr-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
27615     (write-int32-hex-buffered *(ebp+8) %eax)
27616     (write-buffered *(ebp+8) ")\n")
27617 $translate-mu-read-from-stream-stmt:end:
27618     # . restore registers
27619     5f/pop-to-edi
27620     5e/pop-to-esi
27621     59/pop-to-ecx
27622     58/pop-to-eax
27623     # . epilogue
27624     89/<- %esp 5/r32/ebp
27625     5d/pop-to-ebp
27626     c3/return
27627 
27628 translate-mu-write-to-stream-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
27629     # . prologue
27630     55/push-ebp
27631     89/<- %ebp 4/r32/esp
27632     # . save registers
27633     50/push-eax
27634     51/push-ecx
27635     56/push-esi
27636     57/push-edi
27637     # esi = stmt
27638     8b/-> *(ebp+0xc) 6/r32/esi
27639     # var stream/ecx: (addr stmt-var) = stmt->inouts[0]
27640     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
27641     89/<- %ecx 0/r32/eax
27642     # var target/edi: (addr stmt-var) = stmt->inouts[1]
27643     (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
27644     89/<- %edi 0/r32/eax
27645     #
27646     (emit-indent *(ebp+8) *Curr-block-depth)
27647     (write-buffered *(ebp+8) "(write-to-stream")
27648     (emit-subx-call-operand *(ebp+8) %ecx)
27649     (flush *(ebp+8))
27650     (emit-subx-call-operand *(ebp+8) %edi)
27651     (flush *(ebp+8))
27652     (write-buffered *(ebp+8) Space)
27653     (flush *(ebp+8))
27654     (addr-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
27655     (write-int32-hex-buffered *(ebp+8) %eax)
27656     (write-buffered *(ebp+8) ")\n")
27657 $translate-mu-write-to-stream-stmt:end:
27658     # . restore registers
27659     5f/pop-to-edi
27660     5e/pop-to-esi
27661     59/pop-to-ecx
27662     58/pop-to-eax
27663     # . epilogue
27664     89/<- %esp 5/r32/ebp
27665     5d/pop-to-ebp
27666     c3/return
27667 
27668 addr-handle-array-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
27669     # . prologue
27670     55/push-ebp
27671     89/<- %ebp 4/r32/esp
27672     # var t/eax: (addr type-tree) = s->value->type
27673     8b/-> *(ebp+8) 0/r32/eax
27674     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
27675     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
27676     # TODO: check eax != 0
27677     # TODO: check !t->is-atom?
27678     # TODO: check t->left == addr
27679     # t = t->right
27680 $addr-handle-array-payload-size:skip-addr:
27681     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
27682     # TODO: check eax != 0
27683     # TODO: check !t->is-atom?
27684     # TODO: check t->left == handle
27685     # t = t->right
27686 $addr-handle-array-payload-size:skip-handle:
27687     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
27688     # TODO: check eax != 0
27689     # TODO: check !t->is-atom?
27690     # TODO: check t->left == array
27691     # t = t->right
27692 $addr-handle-array-payload-size:skip-array:
27693     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
27694     # TODO: check eax != 0
27695     # if !t->is-atom? t = t->left
27696     81 7/subop/compare *eax 0/imm32/false
27697     {
27698       75/jump-if-!= break/disp8
27699       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
27700     }
27701 $addr-handle-array-payload-size:compute-size:
27702     # TODO: check t->is-atom?
27703     # return size(t->value)
27704     (size-of-type-id-as-array-element *(eax+4))  # Type-tree-value => eax
27705 $addr-handle-array-payload-size:end:
27706     # . epilogue
27707     89/<- %esp 5/r32/ebp
27708     5d/pop-to-ebp
27709     c3/return
27710 
27711 addr-handle-stream-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
27712     # . prologue
27713     55/push-ebp
27714     89/<- %ebp 4/r32/esp
27715     # var t/eax: (addr type-tree) = s->value->type
27716     8b/-> *(ebp+8) 0/r32/eax
27717     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
27718     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
27719     # TODO: check eax != 0
27720     # TODO: check !t->is-atom?
27721     # TODO: check t->left == addr
27722     # t = t->right
27723 $addr-handle-stream-payload-size:skip-addr:
27724     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
27725     # TODO: check eax != 0
27726     # TODO: check !t->is-atom?
27727     # TODO: check t->left == handle
27728     # t = t->right
27729 $addr-handle-stream-payload-size:skip-handle:
27730     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
27731     # TODO: check eax != 0
27732     # TODO: check !t->is-atom?
27733     # TODO: check t->left == stream
27734     # t = t->right
27735 $addr-handle-stream-payload-size:skip-stream:
27736     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
27737     # TODO: check eax != 0
27738     # if !t->is-atom? t = t->left
27739     81 7/subop/compare *eax 0/imm32/false
27740     {
27741       75/jump-if-!= break/disp8
27742       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
27743     }
27744 $addr-handle-stream-payload-size:compute-size:
27745     # TODO: check t->is-atom?
27746     # return size(t->value)
27747     (size-of-type-id-as-array-element *(eax+4))  # Type-tree-value => eax
27748 $addr-handle-stream-payload-size:end:
27749     # . epilogue
27750     89/<- %esp 5/r32/ebp
27751     5d/pop-to-ebp
27752     c3/return
27753 
27754 power-of-2?:  # n: int, err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: boolean
27755     # precondition: n is positive
27756     # . prologue
27757     55/push-ebp
27758     89/<- %ebp 4/r32/esp
27759     # eax = n
27760     8b/-> *(ebp+8) 0/r32/eax
27761     # if (n < 0) abort
27762     3d/compare-eax-with 0/imm32
27763     0f 8c/jump-if-< $power-of-2?:abort/disp32
27764     # var tmp/eax: int = n-1
27765     48/decrement-eax
27766     # var tmp2/eax: int = n & tmp
27767     23/and-> *(ebp+8) 0/r32/eax
27768     # return (tmp2 == 0)
27769     3d/compare-eax-and 0/imm32
27770     0f 94/set-byte-if-= %al
27771     81 4/subop/and %eax 0xff/imm32
27772 $power-of-2?:end:
27773     # . epilogue
27774     89/<- %esp 5/r32/ebp
27775     5d/pop-to-ebp
27776     c3/return
27777 
27778 $power-of-2?:abort:
27779     (write-buffered *(ebp+0xc) "power-of-2?: negative number\n")
27780     (flush *(ebp+0xc))
27781     (stop *(ebp+0x10) 1)
27782     # never gets here
27783 
27784 num-shift-rights:  # n: int -> result/eax: int
27785     # precondition: n is a positive power of 2
27786     # . prologue
27787     55/push-ebp
27788     89/<- %ebp 4/r32/esp
27789     # . save registers
27790     51/push-ecx
27791     # var curr/ecx: int = n
27792     8b/-> *(ebp+8) 1/r32/ecx
27793     # result = 0
27794     b8/copy-to-eax 0/imm32
27795     {
27796       # if (curr <= 1) break
27797       81 7/subop/compare %ecx 1/imm32
27798       7e/jump-if-<= break/disp8
27799       40/increment-eax
27800       c1/shift 5/subop/arithmetic-right %ecx 1/imm8
27801       eb/jump loop/disp8
27802     }
27803 $num-shift-rights:end:
27804     # . restore registers
27805     59/pop-to-ecx
27806     # . epilogue
27807     89/<- %esp 5/r32/ebp
27808     5d/pop-to-ebp
27809     c3/return
27810 
27811 mu-get-offset:  # stmt: (addr stmt) -> result/eax: int
27812     # . prologue
27813     55/push-ebp
27814     89/<- %ebp 4/r32/esp
27815     # var second-inout/eax: (addr stmt-var) = stmt->inouts->next
27816     8b/-> *(ebp+8) 0/r32/eax
27817     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
27818     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
27819     # var output-var/eax: (addr var) = second-inout->value
27820     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
27821 #?     (write-buffered Stderr "mu-get-offset: ")
27822 #?     (write-int32-hex-buffered Stderr %eax)
27823 #?     (write-buffered Stderr " name: ")
27824 #?     50/push-eax
27825 #?     (lookup *eax *(eax+4))  # Var-name
27826 #?     (write-buffered Stderr %eax)
27827 #?     58/pop-to-eax
27828 #?     (write-buffered Stderr Newline)
27829 #?     (flush Stderr)
27830     # return output-var->stack-offset
27831     8b/-> *(eax+0x14) 0/r32/eax  # Var-offset
27832 #?     (write-buffered Stderr "=> ")
27833 #?     (write-int32-hex-buffered Stderr %eax)
27834 #?     (write-buffered Stderr Newline)
27835 #?     (flush Stderr)
27836 $emit-get-offset:end:
27837     # . epilogue
27838     89/<- %esp 5/r32/ebp
27839     5d/pop-to-ebp
27840     c3/return
27841 
27842 emit-subx-block:  # out: (addr buffered-file), block: (addr block), vars: (addr stack live-var), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
27843     # . prologue
27844     55/push-ebp
27845     89/<- %ebp 4/r32/esp
27846     # . save registers
27847     50/push-eax
27848     51/push-ecx
27849     56/push-esi
27850     # esi = block
27851     8b/-> *(ebp+0xc) 6/r32/esi
27852     # block->var->block-depth = *Curr-block-depth
27853     (lookup *(esi+0xc) *(esi+0x10))  # Block-var Block-var => eax
27854     8b/-> *Curr-block-depth 1/r32/ecx
27855     89/<- *(eax+0x10) 1/r32/ecx  # Var-block-depth
27856     # var stmts/eax: (addr list stmt) = lookup(block->statements)
27857     (lookup *(esi+4) *(esi+8))  # Block-stmts Block-stmts => eax
27858     #
27859     {
27860 $emit-subx-block:check-empty:
27861       3d/compare-eax-and 0/imm32
27862       0f 84/jump-if-= break/disp32
27863       (emit-indent *(ebp+8) *Curr-block-depth)
27864       (write-buffered *(ebp+8) "{\n")
27865       # var v/ecx: (addr var) = lookup(block->var)
27866       (lookup *(esi+0xc) *(esi+0x10))  # Block-var Block-var => eax
27867       89/<- %ecx 0/r32/eax
27868       #
27869       (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
27870       (write-buffered *(ebp+8) %eax)
27871       (write-buffered *(ebp+8) ":loop:\n")
27872       ff 0/subop/increment *Curr-block-depth
27873       (push *(ebp+0x10) *(esi+0xc))  # Block-var
27874       (push *(ebp+0x10) *(esi+0x10))  # Block-var
27875       (push *(ebp+0x10) 0)  # false
27876       # emit block->statements
27877       (lookup *(esi+4) *(esi+8))  # Block-stmts Block-stmts => eax
27878       (emit-subx-stmt-list *(ebp+8) %eax *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
27879       (pop *(ebp+0x10))  # => eax
27880       (pop *(ebp+0x10))  # => eax
27881       (pop *(ebp+0x10))  # => eax
27882       ff 1/subop/decrement *Curr-block-depth
27883       (emit-indent *(ebp+8) *Curr-block-depth)
27884       (write-buffered *(ebp+8) "}\n")
27885       (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
27886       (write-buffered *(ebp+8) %eax)
27887       (write-buffered *(ebp+8) ":break:\n")
27888     }
27889 $emit-subx-block:end:
27890     # . restore registers
27891     5e/pop-to-esi
27892     59/pop-to-ecx
27893     58/pop-to-eax
27894     # . epilogue
27895     89/<- %esp 5/r32/ebp
27896     5d/pop-to-ebp
27897     c3/return
27898 
27899 # Primitives supported
27900 # See mu_instructions for a summary of this linked-list data structure.
27901 #
27902 # For each operation, put variants with hard-coded registers before flexible ones.
27903 #
27904 # Unfortunately, our restrictions on addresses require that various fields in
27905 # primitives be handles, which complicates these definitions.
27906 #   - we need to insert dummy fields all over the place for fake alloc-ids
27907 #   - we can't use our syntax sugar of quoted literals for string fields
27908 #
27909 # Fake alloc-ids are needed because our type definitions up top require
27910 # handles but it's clearer to statically allocate these long-lived objects.
27911 # Fake alloc-ids are perfectly safe, but they can't be reclaimed.
27912 #
27913 # Every 'object' below starts with a fake alloc-id. It may also contain other
27914 # fake alloc-ids for various handle fields.
27915 #
27916 # I think of objects starting with a fake alloc-id as having type 'payload'.
27917 # It's not really intended to be created dynamically; for that use `allocate`
27918 # as usual.
27919 #
27920 # Idea for a notation to simplify such definitions:
27921 #   _Primitive-increment-eax:  # (payload primitive)
27922 #     0x11/alloc-id:fake:payload
27923 #     0x11 @(0x11 "increment")  # name
27924 #     0 0                       # inouts
27925 #     0x11 @(0x11/payload
27926 #            0x11 @(0x11/payload  # List-value
27927 #                   0 0             # Var-name
27928 #                   0x11 @(0x11     # Var-type
27929 #                          1/is-atom
27930 #                          1/value 0/unused   # Type-tree-left
27931 #                          0 0                # Type-tree-right
27932 #                         )
27933 #                   1               # block-depth
27934 #                   0               # stack-offset
27935 #                   0x11 @(0x11 "eax")  # Var-register
27936 #                  )
27937 #            0 0)                 # List-next
27938 #     ...
27939 #     _Primitive-increment-ecx/imm32/next
27940 #   ...
27941 # Awfully complex and non-obvious. But also clearly signals there's something
27942 # to learn here, so may be worth trying.
27943 #
27944 # '@' is just an initial thought. Punctuation used so far in Mu: () * % # / "
27945 #
27946 # For now we'll continue to just use comments and manually ensure they stay up
27947 # to date.
27948 == data
27949 Primitives:  # (addr primitive)
27950 # - increment/decrement
27951 _Primitive-increment-eax:  # (addr primitive)
27952     # var/eax <- increment => 40/increment-eax
27953     0x11/imm32/alloc-id:fake
27954     _string-increment/imm32/name
27955     0/imm32/no-inouts
27956     0/imm32/no-inouts
27957     0x11/imm32/alloc-id:fake
27958     Single-int-var-in-eax/imm32/outputs
27959     0x11/imm32/alloc-id:fake
27960     _string_40_increment_eax/imm32/subx-name
27961     0/imm32/no-rm32
27962     0/imm32/no-r32
27963     0/imm32/no-imm32
27964     0/imm32/no-imm8
27965     0/imm32/no-disp32
27966     0/imm32/no-xm32
27967     0/imm32/no-x32
27968     0x11/imm32/alloc-id:fake
27969     _Primitive-increment-ecx/imm32/next
27970 _Primitive-increment-ecx:  # (payload primitive)
27971     0x11/imm32/alloc-id:fake:payload
27972     # var/ecx <- increment => 41/increment-ecx
27973     0x11/imm32/alloc-id:fake
27974     _string-increment/imm32/name
27975     0/imm32/no-inouts
27976     0/imm32/no-inouts
27977     0x11/imm32/alloc-id:fake
27978     Single-int-var-in-ecx/imm32/outputs
27979     0x11/imm32/alloc-id:fake
27980     _string_41_increment_ecx/imm32/subx-name
27981     0/imm32/no-rm32
27982     0/imm32/no-r32
27983     0/imm32/no-imm32
27984     0/imm32/no-imm8
27985     0/imm32/no-disp32
27986     0/imm32/no-xm32
27987     0/imm32/no-x32
27988     0x11/imm32/alloc-id:fake
27989     _Primitive-increment-edx/imm32/next
27990 _Primitive-increment-edx:  # (payload primitive)
27991     0x11/imm32/alloc-id:fake:payload
27992     # var/edx <- increment => 42/increment-edx
27993     0x11/imm32/alloc-id:fake
27994     _string-increment/imm32/name
27995     0/imm32/no-inouts
27996     0/imm32/no-inouts
27997     0x11/imm32/alloc-id:fake
27998     Single-int-var-in-edx/imm32/outputs
27999     0x11/imm32/alloc-id:fake
28000     _string_42_increment_edx/imm32/subx-name
28001     0/imm32/no-rm32
28002     0/imm32/no-r32
28003     0/imm32/no-imm32
28004     0/imm32/no-imm8
28005     0/imm32/no-disp32
28006     0/imm32/no-xm32
28007     0/imm32/no-x32
28008     0x11/imm32/alloc-id:fake
28009     _Primitive-increment-ebx/imm32/next
28010 _Primitive-increment-ebx:  # (payload primitive)
28011     0x11/imm32/alloc-id:fake:payload
28012     # var/ebx <- increment => 43/increment-ebx
28013     0x11/imm32/alloc-id:fake
28014     _string-increment/imm32/name
28015     0/imm32/no-inouts
28016     0/imm32/no-inouts
28017     0x11/imm32/alloc-id:fake
28018     Single-int-var-in-ebx/imm32/outputs
28019     0x11/imm32/alloc-id:fake
28020     _string_43_increment_ebx/imm32/subx-name
28021     0/imm32/no-rm32
28022     0/imm32/no-r32
28023     0/imm32/no-imm32
28024     0/imm32/no-imm8
28025     0/imm32/no-disp32
28026     0/imm32/no-xm32
28027     0/imm32/no-x32
28028     0x11/imm32/alloc-id:fake
28029     _Primitive-increment-esi/imm32/next
28030 _Primitive-increment-esi:  # (payload primitive)
28031     0x11/imm32/alloc-id:fake:payload
28032     # var/esi <- increment => 46/increment-esi
28033     0x11/imm32/alloc-id:fake
28034     _string-increment/imm32/name
28035     0/imm32/no-inouts
28036     0/imm32/no-inouts
28037     0x11/imm32/alloc-id:fake
28038     Single-int-var-in-esi/imm32/outputs
28039     0x11/imm32/alloc-id:fake
28040     _string_46_increment_esi/imm32/subx-name
28041     0/imm32/no-rm32
28042     0/imm32/no-r32
28043     0/imm32/no-imm32
28044     0/imm32/no-imm8
28045     0/imm32/no-disp32
28046     0/imm32/no-xm32
28047     0/imm32/no-x32
28048     0x11/imm32/alloc-id:fake
28049     _Primitive-increment-edi/imm32/next
28050 _Primitive-increment-edi:  # (payload primitive)
28051     0x11/imm32/alloc-id:fake:payload
28052     # var/edi <- increment => 47/increment-edi
28053     0x11/imm32/alloc-id:fake
28054     _string-increment/imm32/name
28055     0/imm32/no-inouts
28056     0/imm32/no-inouts
28057     0x11/imm32/alloc-id:fake
28058     Single-int-var-in-edi/imm32/outputs
28059     0x11/imm32/alloc-id:fake
28060     _string_47_increment_edi/imm32/subx-name
28061     0/imm32/no-rm32
28062     0/imm32/no-r32
28063     0/imm32/no-imm32
28064     0/imm32/no-imm8
28065     0/imm32/no-disp32
28066     0/imm32/no-xm32
28067     0/imm32/no-x32
28068     0x11/imm32/alloc-id:fake
28069     _Primitive-decrement-eax/imm32/next
28070 _Primitive-decrement-eax:  # (payload primitive)
28071     0x11/imm32/alloc-id:fake:payload
28072     # var/eax <- decrement => 48/decrement-eax
28073     0x11/imm32/alloc-id:fake
28074     _string-decrement/imm32/name
28075     0/imm32/no-inouts
28076     0/imm32/no-inouts
28077     0x11/imm32/alloc-id:fake
28078     Single-int-var-in-eax/imm32/outputs
28079     0x11/imm32/alloc-id:fake
28080     _string_48_decrement_eax/imm32/subx-name
28081     0/imm32/no-rm32
28082     0/imm32/no-r32
28083     0/imm32/no-imm32
28084     0/imm32/no-imm8
28085     0/imm32/no-disp32
28086     0/imm32/no-xm32
28087     0/imm32/no-x32
28088     0x11/imm32/alloc-id:fake
28089     _Primitive-decrement-ecx/imm32/next
28090 _Primitive-decrement-ecx:  # (payload primitive)
28091     0x11/imm32/alloc-id:fake:payload
28092     # var/ecx <- decrement => 49/decrement-ecx
28093     0x11/imm32/alloc-id:fake
28094     _string-decrement/imm32/name
28095     0/imm32/no-inouts
28096     0/imm32/no-inouts
28097     0x11/imm32/alloc-id:fake
28098     Single-int-var-in-ecx/imm32/outputs
28099     0x11/imm32/alloc-id:fake
28100     _string_49_decrement_ecx/imm32/subx-name
28101     0/imm32/no-rm32
28102     0/imm32/no-r32
28103     0/imm32/no-imm32
28104     0/imm32/no-imm8
28105     0/imm32/no-disp32
28106     0/imm32/no-xm32
28107     0/imm32/no-x32
28108     0x11/imm32/alloc-id:fake
28109     _Primitive-decrement-edx/imm32/next
28110 _Primitive-decrement-edx:  # (payload primitive)
28111     0x11/imm32/alloc-id:fake:payload
28112     # var/edx <- decrement => 4a/decrement-edx
28113     0x11/imm32/alloc-id:fake
28114     _string-decrement/imm32/name
28115     0/imm32/no-inouts
28116     0/imm32/no-inouts
28117     0x11/imm32/alloc-id:fake
28118     Single-int-var-in-edx/imm32/outputs
28119     0x11/imm32/alloc-id:fake
28120     _string_4a_decrement_edx/imm32/subx-name
28121     0/imm32/no-rm32
28122     0/imm32/no-r32
28123     0/imm32/no-imm32
28124     0/imm32/no-imm8
28125     0/imm32/no-disp32
28126     0/imm32/no-xm32
28127     0/imm32/no-x32
28128     0x11/imm32/alloc-id:fake
28129     _Primitive-decrement-ebx/imm32/next
28130 _Primitive-decrement-ebx:  # (payload primitive)
28131     0x11/imm32/alloc-id:fake:payload
28132     # var/ebx <- decrement => 4b/decrement-ebx
28133     0x11/imm32/alloc-id:fake
28134     _string-decrement/imm32/name
28135     0/imm32/no-inouts
28136     0/imm32/no-inouts
28137     0x11/imm32/alloc-id:fake
28138     Single-int-var-in-ebx/imm32/outputs
28139     0x11/imm32/alloc-id:fake
28140     _string_4b_decrement_ebx/imm32/subx-name
28141     0/imm32/no-rm32
28142     0/imm32/no-r32
28143     0/imm32/no-imm32
28144     0/imm32/no-imm8
28145     0/imm32/no-disp32
28146     0/imm32/no-xm32
28147     0/imm32/no-x32
28148     0x11/imm32/alloc-id:fake
28149     _Primitive-decrement-esi/imm32/next
28150 _Primitive-decrement-esi:  # (payload primitive)
28151     0x11/imm32/alloc-id:fake:payload
28152     # var/esi <- decrement => 4e/decrement-esi
28153     0x11/imm32/alloc-id:fake
28154     _string-decrement/imm32/name
28155     0/imm32/no-inouts
28156     0/imm32/no-inouts
28157     0x11/imm32/alloc-id:fake
28158     Single-int-var-in-esi/imm32/outputs
28159     0x11/imm32/alloc-id:fake
28160     _string_4e_decrement_esi/imm32/subx-name
28161     0/imm32/no-rm32
28162     0/imm32/no-r32
28163     0/imm32/no-imm32
28164     0/imm32/no-imm8
28165     0/imm32/no-disp32
28166     0/imm32/no-xm32
28167     0/imm32/no-x32
28168     0x11/imm32/alloc-id:fake
28169     _Primitive-decrement-edi/imm32/next
28170 _Primitive-decrement-edi:  # (payload primitive)
28171     0x11/imm32/alloc-id:fake:payload
28172     # var/edi <- decrement => 4f/decrement-edi
28173     0x11/imm32/alloc-id:fake
28174     _string-decrement/imm32/name
28175     0/imm32/no-inouts
28176     0/imm32/no-inouts
28177     0x11/imm32/alloc-id:fake
28178     Single-int-var-in-edi/imm32/outputs
28179     0x11/imm32/alloc-id:fake
28180     _string_4f_decrement_edi/imm32/subx-name
28181     0/imm32/no-rm32
28182     0/imm32/no-r32
28183     0/imm32/no-imm32
28184     0/imm32/no-imm8
28185     0/imm32/no-disp32
28186     0/imm32/no-xm32
28187     0/imm32/no-x32
28188     0x11/imm32/alloc-id:fake
28189     _Primitive-increment-mem/imm32/next
28190 _Primitive-increment-mem:  # (payload primitive)
28191     0x11/imm32/alloc-id:fake:payload
28192     # increment var => ff 0/subop/increment *(ebp+__)
28193     0x11/imm32/alloc-id:fake
28194     _string-increment/imm32/name
28195     0x11/imm32/alloc-id:fake
28196     Single-int-var-in-mem/imm32/inouts
28197     0/imm32/no-outputs
28198     0/imm32/no-outputs
28199     0x11/imm32/alloc-id:fake
28200     _string_ff_subop_increment/imm32/subx-name
28201     1/imm32/rm32-is-first-inout
28202     0/imm32/no-r32
28203     0/imm32/no-imm32
28204     0/imm32/no-imm8
28205     0/imm32/no-disp32
28206     0/imm32/no-xm32
28207     0/imm32/no-x32
28208     0x11/imm32/alloc-id:fake
28209     _Primitive-increment-reg/imm32/next
28210 _Primitive-increment-reg:  # (payload primitive)
28211     0x11/imm32/alloc-id:fake:payload
28212     # var/reg <- increment => ff 0/subop/increment %__
28213     0x11/imm32/alloc-id:fake
28214     _string-increment/imm32/name
28215     0/imm32/no-inouts
28216     0/imm32/no-inouts
28217     0x11/imm32/alloc-id:fake
28218     Single-int-var-in-some-register/imm32/outputs
28219     0x11/imm32/alloc-id:fake
28220     _string_ff_subop_increment/imm32/subx-name
28221     3/imm32/rm32-is-first-output
28222     0/imm32/no-r32
28223     0/imm32/no-imm32
28224     0/imm32/no-imm8
28225     0/imm32/no-disp32
28226     0/imm32/no-xm32
28227     0/imm32/no-x32
28228     0x11/imm32/alloc-id:fake
28229     _Primitive-decrement-mem/imm32/next
28230 _Primitive-decrement-mem:  # (payload primitive)
28231     0x11/imm32/alloc-id:fake:payload
28232     # decrement var => ff 1/subop/decrement *(ebp+__)
28233     0x11/imm32/alloc-id:fake
28234     _string-decrement/imm32/name
28235     0x11/imm32/alloc-id:fake
28236     Single-int-var-in-mem/imm32/inouts
28237     0/imm32/no-outputs
28238     0/imm32/no-outputs
28239     0x11/imm32/alloc-id:fake
28240     _string_ff_subop_decrement/imm32/subx-name
28241     1/imm32/rm32-is-first-inout
28242     0/imm32/no-r32
28243     0/imm32/no-imm32
28244     0/imm32/no-imm8
28245     0/imm32/no-disp32
28246     0/imm32/no-xm32
28247     0/imm32/no-x32
28248     0x11/imm32/alloc-id:fake
28249     _Primitive-decrement-reg/imm32/next
28250 _Primitive-decrement-reg:  # (payload primitive)
28251     0x11/imm32/alloc-id:fake:payload
28252     # var/reg <- decrement => ff 1/subop/decrement %__
28253     0x11/imm32/alloc-id:fake
28254     _string-decrement/imm32/name
28255     0/imm32/no-inouts
28256     0/imm32/no-inouts
28257     0x11/imm32/alloc-id:fake
28258     Single-int-var-in-some-register/imm32/outputs
28259     0x11/imm32/alloc-id:fake
28260     _string_ff_subop_decrement/imm32/subx-name
28261     3/imm32/rm32-is-first-output
28262     0/imm32/no-r32
28263     0/imm32/no-imm32
28264     0/imm32/no-imm8
28265     0/imm32/no-disp32
28266     0/imm32/no-xm32
28267     0/imm32/no-x32
28268     0x11/imm32/alloc-id:fake
28269     _Primitive-add-to-eax/imm32/next
28270 # - add
28271 _Primitive-add-to-eax:  # (payload primitive)
28272     0x11/imm32/alloc-id:fake:payload
28273     # var/eax <- add lit => 05/add-to-eax lit/imm32
28274     0x11/imm32/alloc-id:fake
28275     _string-add/imm32/name
28276     0x11/imm32/alloc-id:fake
28277     Single-lit-var/imm32/inouts
28278     0x11/imm32/alloc-id:fake
28279     Single-int-var-in-eax/imm32/outputs
28280     0x11/imm32/alloc-id:fake
28281     _string_05_add_to_eax/imm32/subx-name
28282     0/imm32/no-rm32
28283     0/imm32/no-r32
28284     1/imm32/imm32-is-first-inout
28285     0/imm32/no-imm8
28286     0/imm32/no-disp32
28287     0/imm32/no-xm32
28288     0/imm32/no-x32
28289     0x11/imm32/alloc-id:fake
28290     _Primitive-add-reg-to-reg/imm32/next
28291 _Primitive-add-reg-to-reg:  # (payload primitive)
28292     0x11/imm32/alloc-id:fake:payload
28293     # var1/reg <- add var2/reg => 01/add-to var1/rm32 var2/r32
28294     0x11/imm32/alloc-id:fake
28295     _string-add/imm32/name
28296     0x11/imm32/alloc-id:fake
28297     Single-int-var-in-some-register/imm32/inouts
28298     0x11/imm32/alloc-id:fake
28299     Single-int-var-in-some-register/imm32/outputs
28300     0x11/imm32/alloc-id:fake
28301     _string_01_add_to/imm32/subx-name
28302     3/imm32/rm32-is-first-output
28303     1/imm32/r32-is-first-inout
28304     0/imm32/no-imm32
28305     0/imm32/no-imm8
28306     0/imm32/no-disp32
28307     0/imm32/no-xm32
28308     0/imm32/no-x32
28309     0x11/imm32/alloc-id:fake
28310     _Primitive-add-reg-to-mem/imm32/next
28311 _Primitive-add-reg-to-mem:  # (payload primitive)
28312     0x11/imm32/alloc-id:fake:payload
28313     # add-to var1 var2/reg => 01/add-to var1 var2/r32
28314     0x11/imm32/alloc-id:fake
28315     _string-add-to/imm32/name
28316     0x11/imm32/alloc-id:fake
28317     Two-args-int-stack-int-reg/imm32/inouts
28318     0/imm32/no-outputs
28319     0/imm32/no-outputs
28320     0x11/imm32/alloc-id:fake
28321     _string_01_add_to/imm32/subx-name
28322     1/imm32/rm32-is-first-inout
28323     2/imm32/r32-is-second-inout
28324     0/imm32/no-imm32
28325     0/imm32/no-imm8
28326     0/imm32/no-disp32
28327     0/imm32/no-xm32
28328     0/imm32/no-x32
28329     0x11/imm32/alloc-id:fake
28330     _Primitive-add-mem-to-reg/imm32/next
28331 _Primitive-add-mem-to-reg:  # (payload primitive)
28332     0x11/imm32/alloc-id:fake:payload
28333     # var1/reg <- add var2 => 03/add var2/rm32 var1/r32
28334     0x11/imm32/alloc-id:fake
28335     _string-add/imm32/name
28336     0x11/imm32/alloc-id:fake
28337     Single-int-var-in-mem/imm32/inouts
28338     0x11/imm32/alloc-id:fake
28339     Single-int-var-in-some-register/imm32/outputs
28340     0x11/imm32/alloc-id:fake
28341     _string_03_add/imm32/subx-name
28342     1/imm32/rm32-is-first-inout
28343     3/imm32/r32-is-first-output
28344     0/imm32/no-imm32
28345     0/imm32/no-imm8
28346     0/imm32/no-disp32
28347     0/imm32/no-xm32
28348     0/imm32/no-x32
28349     0x11/imm32/alloc-id:fake
28350     _Primitive-add-lit-to-reg/imm32/next
28351 _Primitive-add-lit-to-reg:  # (payload primitive)
28352     0x11/imm32/alloc-id:fake:payload
28353     # var1/reg <- add lit => 81 0/subop/add var1/rm32 lit/imm32
28354     0x11/imm32/alloc-id:fake
28355     _string-add/imm32/name
28356     0x11/imm32/alloc-id:fake
28357     Single-lit-var/imm32/inouts
28358     0x11/imm32/alloc-id:fake
28359     Single-int-var-in-some-register/imm32/outputs
28360     0x11/imm32/alloc-id:fake
28361     _string_81_subop_add/imm32/subx-name
28362     3/imm32/rm32-is-first-output
28363     0/imm32/no-r32
28364     1/imm32/imm32-is-first-inout
28365     0/imm32/no-imm8
28366     0/imm32/no-disp32
28367     0/imm32/no-xm32
28368     0/imm32/no-x32
28369     0x11/imm32/alloc-id:fake
28370     _Primitive-add-lit-to-mem/imm32/next
28371 _Primitive-add-lit-to-mem:  # (payload primitive)
28372     0x11/imm32/alloc-id:fake:payload
28373     # add-to var1, lit => 81 0/subop/add var1/rm32 lit/imm32
28374     0x11/imm32/alloc-id:fake
28375     _string-add-to/imm32/name
28376     0x11/imm32/alloc-id:fake
28377     Int-var-and-literal/imm32/inouts
28378     0/imm32/no-outputs
28379     0/imm32/no-outputs
28380     0x11/imm32/alloc-id:fake
28381     _string_81_subop_add/imm32/subx-name
28382     1/imm32/rm32-is-first-inout
28383     0/imm32/no-r32
28384     2/imm32/imm32-is-second-inout
28385     0/imm32/no-imm8
28386     0/imm32/no-disp32
28387     0/imm32/no-xm32
28388     0/imm32/no-x32
28389     0x11/imm32/alloc-id:fake
28390     _Primitive-subtract-from-eax/imm32/next
28391 # - subtract
28392 _Primitive-subtract-from-eax:  # (payload primitive)
28393     0x11/imm32/alloc-id:fake:payload
28394     # var/eax <- subtract lit => 2d/subtract-from-eax lit/imm32
28395     0x11/imm32/alloc-id:fake
28396     _string-subtract/imm32/name
28397     0x11/imm32/alloc-id:fake
28398     Single-lit-var/imm32/inouts
28399     0x11/imm32/alloc-id:fake
28400     Single-int-var-in-eax/imm32/outputs
28401     0x11/imm32/alloc-id:fake
28402     _string_2d_subtract_from_eax/imm32/subx-name
28403     0/imm32/no-rm32
28404     0/imm32/no-r32
28405     1/imm32/imm32-is-first-inout
28406     0/imm32/no-imm8
28407     0/imm32/no-disp32
28408     0/imm32/no-xm32
28409     0/imm32/no-x32
28410     0x11/imm32/alloc-id:fake
28411     _Primitive-subtract-reg-from-reg/imm32/next
28412 _Primitive-subtract-reg-from-reg:  # (payload primitive)
28413     0x11/imm32/alloc-id:fake:payload
28414     # var1/reg <- subtract var2/reg => 29/subtract-from var1/rm32 var2/r32
28415     0x11/imm32/alloc-id:fake
28416     _string-subtract/imm32/name
28417     0x11/imm32/alloc-id:fake
28418     Single-int-var-in-some-register/imm32/inouts
28419     0x11/imm32/alloc-id:fake
28420     Single-int-var-in-some-register/imm32/outputs
28421     0x11/imm32/alloc-id:fake
28422     _string_29_subtract_from/imm32/subx-name
28423     3/imm32/rm32-is-first-output
28424     1/imm32/r32-is-first-inout
28425     0/imm32/no-imm32
28426     0/imm32/no-imm8
28427     0/imm32/no-disp32
28428     0/imm32/no-xm32
28429     0/imm32/no-x32
28430     0x11/imm32/alloc-id:fake
28431     _Primitive-subtract-reg-from-mem/imm32/next
28432 _Primitive-subtract-reg-from-mem:  # (payload primitive)
28433     0x11/imm32/alloc-id:fake:payload
28434     # subtract-from var1 var2/reg => 29/subtract-from var1 var2/r32
28435     0x11/imm32/alloc-id:fake
28436     _string-subtract-from/imm32/name
28437     0x11/imm32/alloc-id:fake
28438     Two-args-int-stack-int-reg/imm32/inouts
28439     0/imm32/no-outputs
28440     0/imm32/no-outputs
28441     0x11/imm32/alloc-id:fake
28442     _string_29_subtract_from/imm32/subx-name
28443     1/imm32/rm32-is-first-inout
28444     2/imm32/r32-is-second-inout
28445     0/imm32/no-imm32
28446     0/imm32/no-imm8
28447     0/imm32/no-disp32
28448     0/imm32/no-xm32
28449     0/imm32/no-x32
28450     0x11/imm32/alloc-id:fake
28451     _Primitive-subtract-mem-from-reg/imm32/next
28452 _Primitive-subtract-mem-from-reg:  # (payload primitive)
28453     0x11/imm32/alloc-id:fake:payload
28454     # var1/reg <- subtract var2 => 2b/subtract var2/rm32 var1/r32
28455     0x11/imm32/alloc-id:fake
28456     _string-subtract/imm32/name
28457     0x11/imm32/alloc-id:fake
28458     Single-int-var-in-mem/imm32/inouts
28459     0x11/imm32/alloc-id:fake
28460     Single-int-var-in-some-register/imm32/outputs
28461     0x11/imm32/alloc-id:fake
28462     _string_2b_subtract/imm32/subx-name
28463     1/imm32/rm32-is-first-inout
28464     3/imm32/r32-is-first-output
28465     0/imm32/no-imm32
28466     0/imm32/no-imm8
28467     0/imm32/no-disp32
28468     0/imm32/no-xm32
28469     0/imm32/no-x32
28470     0x11/imm32/alloc-id:fake
28471     _Primitive-subtract-lit-from-reg/imm32/next
28472 _Primitive-subtract-lit-from-reg:  # (payload primitive)
28473     0x11/imm32/alloc-id:fake:payload
28474     # var1/reg <- subtract lit => 81 5/subop/subtract var1/rm32 lit/imm32
28475     0x11/imm32/alloc-id:fake
28476     _string-subtract/imm32/name
28477     0x11/imm32/alloc-id:fake
28478     Single-lit-var/imm32/inouts
28479     0x11/imm32/alloc-id:fake
28480     Single-int-var-in-some-register/imm32/outputs
28481     0x11/imm32/alloc-id:fake
28482     _string_81_subop_subtract/imm32/subx-name
28483     3/imm32/rm32-is-first-output
28484     0/imm32/no-r32
28485     1/imm32/imm32-is-first-inout
28486     0/imm32/no-imm8
28487     0/imm32/no-disp32
28488     0/imm32/no-xm32
28489     0/imm32/no-x32
28490     0x11/imm32/alloc-id:fake
28491     _Primitive-subtract-lit-from-mem/imm32/next
28492 _Primitive-subtract-lit-from-mem:  # (payload primitive)
28493     0x11/imm32/alloc-id:fake:payload
28494     # subtract-from var1, lit => 81 5/subop/subtract var1/rm32 lit/imm32
28495     0x11/imm32/alloc-id:fake
28496     _string-subtract-from/imm32/name
28497     0x11/imm32/alloc-id:fake
28498     Int-var-and-literal/imm32/inouts
28499     0/imm32/no-outputs
28500     0/imm32/no-outputs
28501     0x11/imm32/alloc-id:fake
28502     _string_81_subop_subtract/imm32/subx-name
28503     1/imm32/rm32-is-first-inout
28504     0/imm32/no-r32
28505     2/imm32/imm32-is-second-inout
28506     0/imm32/no-imm8
28507     0/imm32/no-disp32
28508     0/imm32/no-xm32
28509     0/imm32/no-x32
28510     0x11/imm32/alloc-id:fake
28511     _Primitive-and-with-eax/imm32/next
28512 # - and
28513 _Primitive-and-with-eax:  # (payload primitive)
28514     0x11/imm32/alloc-id:fake:payload
28515     # var/eax <- and lit => 25/and-with-eax lit/imm32
28516     0x11/imm32/alloc-id:fake
28517     _string-and/imm32/name
28518     0x11/imm32/alloc-id:fake
28519     Single-lit-var/imm32/inouts
28520     0x11/imm32/alloc-id:fake
28521     Single-int-var-in-eax/imm32/outputs
28522     0x11/imm32/alloc-id:fake
28523     _string_25_and_with_eax/imm32/subx-name
28524     0/imm32/no-rm32
28525     0/imm32/no-r32
28526     1/imm32/imm32-is-first-inout
28527     0/imm32/no-imm8
28528     0/imm32/no-disp32
28529     0/imm32/no-xm32
28530     0/imm32/no-x32
28531     0x11/imm32/alloc-id:fake
28532     _Primitive-and-reg-with-reg/imm32/next
28533 _Primitive-and-reg-with-reg:  # (payload primitive)
28534     0x11/imm32/alloc-id:fake:payload
28535     # var1/reg <- and var2/reg => 21/and-with var1/rm32 var2/r32
28536     0x11/imm32/alloc-id:fake
28537     _string-and/imm32/name
28538     0x11/imm32/alloc-id:fake
28539     Single-int-var-in-some-register/imm32/inouts
28540     0x11/imm32/alloc-id:fake
28541     Single-int-var-in-some-register/imm32/outputs
28542     0x11/imm32/alloc-id:fake
28543     _string_21_and_with/imm32/subx-name
28544     3/imm32/rm32-is-first-output
28545     1/imm32/r32-is-first-inout
28546     0/imm32/no-imm32
28547     0/imm32/no-imm8
28548     0/imm32/no-disp32
28549     0/imm32/no-xm32
28550     0/imm32/no-x32
28551     0x11/imm32/alloc-id:fake
28552     _Primitive-and-reg-with-mem/imm32/next
28553 _Primitive-and-reg-with-mem:  # (payload primitive)
28554     0x11/imm32/alloc-id:fake:payload
28555     # and-with var1 var2/reg => 21/and-with var1 var2/r32
28556     0x11/imm32/alloc-id:fake
28557     _string-and-with/imm32/name
28558     0x11/imm32/alloc-id:fake
28559     Two-args-int-stack-int-reg/imm32/inouts
28560     0/imm32/no-outputs
28561     0/imm32/no-outputs
28562     0x11/imm32/alloc-id:fake
28563     _string_21_and_with/imm32/subx-name
28564     1/imm32/rm32-is-first-inout
28565     2/imm32/r32-is-second-inout
28566     0/imm32/no-imm32
28567     0/imm32/no-imm8
28568     0/imm32/no-disp32
28569     0/imm32/no-xm32
28570     0/imm32/no-x32
28571     0x11/imm32/alloc-id:fake
28572     _Primitive-and-mem-with-reg/imm32/next
28573 _Primitive-and-mem-with-reg:  # (payload primitive)
28574     0x11/imm32/alloc-id:fake:payload
28575     # var1/reg <- and var2 => 23/and var2/rm32 var1/r32
28576     0x11/imm32/alloc-id:fake
28577     _string-and/imm32/name
28578     0x11/imm32/alloc-id:fake
28579     Single-int-var-in-mem/imm32/inouts
28580     0x11/imm32/alloc-id:fake
28581     Single-int-var-in-some-register/imm32/outputs
28582     0x11/imm32/alloc-id:fake
28583     _string_23_and/imm32/subx-name
28584     1/imm32/rm32-is-first-inout
28585     3/imm32/r32-is-first-output
28586     0/imm32/no-imm32
28587     0/imm32/no-imm8
28588     0/imm32/no-disp32
28589     0/imm32/no-xm32
28590     0/imm32/no-x32
28591     0x11/imm32/alloc-id:fake
28592     _Primitive-and-lit-with-reg/imm32/next
28593 _Primitive-and-lit-with-reg:  # (payload primitive)
28594     0x11/imm32/alloc-id:fake:payload
28595     # var1/reg <- and lit => 81 4/subop/and var1/rm32 lit/imm32
28596     0x11/imm32/alloc-id:fake
28597     _string-and/imm32/name
28598     0x11/imm32/alloc-id:fake
28599     Single-lit-var/imm32/inouts
28600     0x11/imm32/alloc-id:fake
28601     Single-int-var-in-some-register/imm32/outputs
28602     0x11/imm32/alloc-id:fake
28603     _string_81_subop_and/imm32/subx-name
28604     3/imm32/rm32-is-first-output
28605     0/imm32/no-r32
28606     1/imm32/imm32-is-first-inout
28607     0/imm32/no-imm8
28608     0/imm32/no-disp32
28609     0/imm32/no-xm32
28610     0/imm32/no-x32
28611     0x11/imm32/alloc-id:fake
28612     _Primitive-and-lit-with-mem/imm32/next
28613 _Primitive-and-lit-with-mem:  # (payload primitive)
28614     0x11/imm32/alloc-id:fake:payload
28615     # and-with var1, lit => 81 4/subop/and var1/rm32 lit/imm32
28616     0x11/imm32/alloc-id:fake
28617     _string-and-with/imm32/name
28618     0x11/imm32/alloc-id:fake
28619     Int-var-and-literal/imm32/inouts
28620     0/imm32/no-outputs
28621     0/imm32/no-outputs
28622     0x11/imm32/alloc-id:fake
28623     _string_81_subop_and/imm32/subx-name
28624     1/imm32/rm32-is-first-inout
28625     0/imm32/no-r32
28626     2/imm32/imm32-is-second-inout
28627     0/imm32/no-imm8
28628     0/imm32/no-disp32
28629     0/imm32/no-xm32
28630     0/imm32/no-x32
28631     0x11/imm32/alloc-id:fake
28632     _Primitive-or-with-eax/imm32/next
28633 # - or
28634 _Primitive-or-with-eax:  # (payload primitive)
28635     0x11/imm32/alloc-id:fake:payload
28636     # var/eax <- or lit => 0d/or-with-eax lit/imm32
28637     0x11/imm32/alloc-id:fake
28638     _string-or/imm32/name
28639     0x11/imm32/alloc-id:fake
28640     Single-lit-var/imm32/inouts
28641     0x11/imm32/alloc-id:fake
28642     Single-int-var-in-eax/imm32/outputs
28643     0x11/imm32/alloc-id:fake
28644     _string_0d_or_with_eax/imm32/subx-name
28645     0/imm32/no-rm32
28646     0/imm32/no-r32
28647     1/imm32/imm32-is-first-inout
28648     0/imm32/no-imm8
28649     0/imm32/no-disp32
28650     0/imm32/no-xm32
28651     0/imm32/no-x32
28652     0x11/imm32/alloc-id:fake
28653     _Primitive-or-reg-with-reg/imm32/next
28654 _Primitive-or-reg-with-reg:  # (payload primitive)
28655     0x11/imm32/alloc-id:fake:payload
28656     # var1/reg <- or var2/reg => 09/or-with var1/rm32 var2/r32
28657     0x11/imm32/alloc-id:fake
28658     _string-or/imm32/name
28659     0x11/imm32/alloc-id:fake
28660     Single-int-var-in-some-register/imm32/inouts
28661     0x11/imm32/alloc-id:fake
28662     Single-int-var-in-some-register/imm32/outputs
28663     0x11/imm32/alloc-id:fake
28664     _string_09_or_with/imm32/subx-name
28665     3/imm32/rm32-is-first-output
28666     1/imm32/r32-is-first-inout
28667     0/imm32/no-imm32
28668     0/imm32/no-imm8
28669     0/imm32/no-disp32
28670     0/imm32/no-xm32
28671     0/imm32/no-x32
28672     0x11/imm32/alloc-id:fake
28673     _Primitive-or-reg-with-mem/imm32/next
28674 _Primitive-or-reg-with-mem:  # (payload primitive)
28675     0x11/imm32/alloc-id:fake:payload
28676     # or-with var1 var2/reg => 09/or-with var1 var2/r32
28677     0x11/imm32/alloc-id:fake
28678     _string-or-with/imm32/name
28679     0x11/imm32/alloc-id:fake
28680     Two-args-int-stack-int-reg/imm32/inouts
28681     0/imm32/no-outputs
28682     0/imm32/no-outputs
28683     0x11/imm32/alloc-id:fake
28684     _string_09_or_with/imm32/subx-name
28685     1/imm32/rm32-is-first-inout
28686     2/imm32/r32-is-second-inout
28687     0/imm32/no-imm32
28688     0/imm32/no-imm8
28689     0/imm32/no-disp32
28690     0/imm32/no-xm32
28691     0/imm32/no-x32
28692     0x11/imm32/alloc-id:fake
28693     _Primitive-or-mem-with-reg/imm32/next
28694 _Primitive-or-mem-with-reg:  # (payload primitive)
28695     0x11/imm32/alloc-id:fake:payload
28696     # var1/reg <- or var2 => 0b/or var2/rm32 var1/r32
28697     0x11/imm32/alloc-id:fake
28698     _string-or/imm32/name
28699     0x11/imm32/alloc-id:fake
28700     Single-int-var-in-mem/imm32/inouts
28701     0x11/imm32/alloc-id:fake
28702     Single-int-var-in-some-register/imm32/outputs
28703     0x11/imm32/alloc-id:fake
28704     _string_0b_or/imm32/subx-name
28705     1/imm32/rm32-is-first-inout
28706     3/imm32/r32-is-first-output
28707     0/imm32/no-imm32
28708     0/imm32/no-imm8
28709     0/imm32/no-disp32
28710     0/imm32/no-xm32
28711     0/imm32/no-x32
28712     0x11/imm32/alloc-id:fake
28713     _Primitive-or-lit-with-reg/imm32/next
28714 _Primitive-or-lit-with-reg:  # (payload primitive)
28715     0x11/imm32/alloc-id:fake:payload
28716     # var1/reg <- or lit => 81 1/subop/or var1/rm32 lit/imm32
28717     0x11/imm32/alloc-id:fake
28718     _string-or/imm32/name
28719     0x11/imm32/alloc-id:fake
28720     Single-lit-var/imm32/inouts
28721     0x11/imm32/alloc-id:fake
28722     Single-int-var-in-some-register/imm32/outputs
28723     0x11/imm32/alloc-id:fake
28724     _string_81_subop_or/imm32/subx-name
28725     3/imm32/rm32-is-first-output
28726     0/imm32/no-r32
28727     1/imm32/imm32-is-first-inout
28728     0/imm32/no-imm8
28729     0/imm32/no-disp32
28730     0/imm32/no-xm32
28731     0/imm32/no-x32
28732     0x11/imm32/alloc-id:fake
28733     _Primitive-or-lit-with-mem/imm32/next
28734 _Primitive-or-lit-with-mem:  # (payload primitive)
28735     0x11/imm32/alloc-id:fake:payload
28736     # or-with var1, lit => 81 1/subop/or var1/rm32 lit/imm32
28737     0x11/imm32/alloc-id:fake
28738     _string-or-with/imm32/name
28739     0x11/imm32/alloc-id:fake
28740     Int-var-and-literal/imm32/inouts
28741     0/imm32/no-outputs
28742     0/imm32/no-outputs
28743     0x11/imm32/alloc-id:fake
28744     _string_81_subop_or/imm32/subx-name
28745     1/imm32/rm32-is-first-inout
28746     0/imm32/no-r32
28747     2/imm32/imm32-is-second-inout
28748     0/imm32/no-imm8
28749     0/imm32/no-disp32
28750     0/imm32/no-xm32
28751     0/imm32/no-x32
28752     0x11/imm32/alloc-id:fake
28753     _Primitive-xor-with-eax/imm32/next
28754 # - xor
28755 _Primitive-xor-with-eax:  # (payload primitive)
28756     0x11/imm32/alloc-id:fake:payload
28757     # var/eax <- xor lit => 35/xor-with-eax lit/imm32
28758     0x11/imm32/alloc-id:fake
28759     _string-xor/imm32/name
28760     0x11/imm32/alloc-id:fake
28761     Single-lit-var/imm32/inouts
28762     0x11/imm32/alloc-id:fake
28763     Single-int-var-in-eax/imm32/outputs
28764     0x11/imm32/alloc-id:fake
28765     _string_35_xor_with_eax/imm32/subx-name
28766     0/imm32/no-rm32
28767     0/imm32/no-r32
28768     1/imm32/imm32-is-first-inout
28769     0/imm32/no-imm8
28770     0/imm32/no-disp32
28771     0/imm32/no-xm32
28772     0/imm32/no-x32
28773     0x11/imm32/alloc-id:fake
28774     _Primitive-xor-reg-with-reg/imm32/next
28775 _Primitive-xor-reg-with-reg:  # (payload primitive)
28776     0x11/imm32/alloc-id:fake:payload
28777     # var1/reg <- xor var2/reg => 31/xor-with var1/rm32 var2/r32
28778     0x11/imm32/alloc-id:fake
28779     _string-xor/imm32/name
28780     0x11/imm32/alloc-id:fake
28781     Single-int-var-in-some-register/imm32/inouts
28782     0x11/imm32/alloc-id:fake
28783     Single-int-var-in-some-register/imm32/outputs
28784     0x11/imm32/alloc-id:fake
28785     _string_31_xor_with/imm32/subx-name
28786     3/imm32/rm32-is-first-output
28787     1/imm32/r32-is-first-inout
28788     0/imm32/no-imm32
28789     0/imm32/no-imm8
28790     0/imm32/no-disp32
28791     0/imm32/no-xm32
28792     0/imm32/no-x32
28793     0x11/imm32/alloc-id:fake
28794     _Primitive-xor-reg-with-mem/imm32/next
28795 _Primitive-xor-reg-with-mem:  # (payload primitive)
28796     0x11/imm32/alloc-id:fake:payload
28797     # xor-with var1 var2/reg => 31/xor-with var1 var2/r32
28798     0x11/imm32/alloc-id:fake
28799     _string-xor-with/imm32/name
28800     0x11/imm32/alloc-id:fake
28801     Two-args-int-stack-int-reg/imm32/inouts
28802     0/imm32/no-outputs
28803     0/imm32/no-outputs
28804     0x11/imm32/alloc-id:fake
28805     _string_31_xor_with/imm32/subx-name
28806     1/imm32/rm32-is-first-inout
28807     2/imm32/r32-is-second-inout
28808     0/imm32/no-imm32
28809     0/imm32/no-imm8
28810     0/imm32/no-disp32
28811     0/imm32/no-xm32
28812     0/imm32/no-x32
28813     0x11/imm32/alloc-id:fake
28814     _Primitive-xor-mem-with-reg/imm32/next
28815 _Primitive-xor-mem-with-reg:  # (payload primitive)
28816     0x11/imm32/alloc-id:fake:payload
28817     # var1/reg <- xor var2 => 33/xor var2/rm32 var1/r32
28818     0x11/imm32/alloc-id:fake
28819     _string-xor/imm32/name
28820     0x11/imm32/alloc-id:fake
28821     Single-int-var-in-mem/imm32/inouts
28822     0x11/imm32/alloc-id:fake
28823     Single-int-var-in-some-register/imm32/outputs
28824     0x11/imm32/alloc-id:fake
28825     _string_33_xor/imm32/subx-name
28826     1/imm32/rm32-is-first-inout
28827     3/imm32/r32-is-first-output
28828     0/imm32/no-imm32
28829     0/imm32/no-imm8
28830     0/imm32/no-disp32
28831     0/imm32/no-xm32
28832     0/imm32/no-x32
28833     0x11/imm32/alloc-id:fake
28834     _Primitive-xor-lit-with-reg/imm32/next
28835 _Primitive-xor-lit-with-reg:  # (payload primitive)
28836     0x11/imm32/alloc-id:fake:payload
28837     # var1/reg <- xor lit => 81 6/subop/xor var1/rm32 lit/imm32
28838     0x11/imm32/alloc-id:fake
28839     _string-xor/imm32/name
28840     0x11/imm32/alloc-id:fake
28841     Single-lit-var/imm32/inouts
28842     0x11/imm32/alloc-id:fake
28843     Single-int-var-in-some-register/imm32/outputs
28844     0x11/imm32/alloc-id:fake
28845     _string_81_subop_xor/imm32/subx-name
28846     3/imm32/rm32-is-first-output
28847     0/imm32/no-r32
28848     1/imm32/imm32-is-first-inout
28849     0/imm32/no-imm8
28850     0/imm32/no-disp32
28851     0/imm32/no-xm32
28852     0/imm32/no-x32
28853     0x11/imm32/alloc-id:fake
28854     _Primitive-xor-lit-with-mem/imm32/next
28855 _Primitive-xor-lit-with-mem:  # (payload primitive)
28856     0x11/imm32/alloc-id:fake:payload
28857     # xor-with var1, lit => 81 6/subop/xor var1/rm32 lit/imm32
28858     0x11/imm32/alloc-id:fake
28859     _string-xor-with/imm32/name
28860     0x11/imm32/alloc-id:fake
28861     Int-var-and-literal/imm32/inouts
28862     0/imm32/no-outputs
28863     0/imm32/no-outputs
28864     0x11/imm32/alloc-id:fake
28865     _string_81_subop_xor/imm32/subx-name
28866     1/imm32/rm32-is-first-inout
28867     0/imm32/no-r32
28868     2/imm32/imm32-is-second-inout
28869     0/imm32/no-imm8
28870     0/imm32/no-disp32
28871     0/imm32/no-xm32
28872     0/imm32/no-x32
28873     0x11/imm32/alloc-id:fake
28874     _Primitive-shift-reg-left-by-lit/imm32/next
28875 _Primitive-shift-reg-left-by-lit:  # (payload primitive)
28876     0x11/imm32/alloc-id:fake:payload
28877     # var1/reg <- shift-left lit => c1/shift 4/subop/left var1/rm32 lit/imm32
28878     0x11/imm32/alloc-id:fake
28879     _string-shift-left/imm32/name
28880     0x11/imm32/alloc-id:fake
28881     Single-lit-var/imm32/inouts
28882     0x11/imm32/alloc-id:fake
28883     Single-int-var-in-some-register/imm32/outputs
28884     0x11/imm32/alloc-id:fake
28885     _string_c1_subop_shift_left/imm32/subx-name
28886     3/imm32/rm32-is-first-output
28887     0/imm32/no-r32
28888     0/imm32/no-imm32
28889     1/imm32/imm8-is-first-inout
28890     0/imm32/no-disp32
28891     0/imm32/no-xm32
28892     0/imm32/no-x32
28893     0x11/imm32/alloc-id:fake
28894     _Primitive-shift-reg-right-by-lit/imm32/next
28895 _Primitive-shift-reg-right-by-lit:  # (payload primitive)
28896     0x11/imm32/alloc-id:fake:payload
28897     # var1/reg <- shift-right lit => c1/shift 5/subop/right var1/rm32 lit/imm32
28898     0x11/imm32/alloc-id:fake
28899     _string-shift-right/imm32/name
28900     0x11/imm32/alloc-id:fake
28901     Single-lit-var/imm32/inouts
28902     0x11/imm32/alloc-id:fake
28903     Single-int-var-in-some-register/imm32/outputs
28904     0x11/imm32/alloc-id:fake
28905     _string_c1_subop_shift_right_padding_zeroes/imm32/subx-name
28906     3/imm32/rm32-is-first-output
28907     0/imm32/no-r32
28908     0/imm32/no-imm32
28909     1/imm32/imm8-is-first-inout
28910     0/imm32/no-disp32
28911     0/imm32/no-xm32
28912     0/imm32/no-x32
28913     0x11/imm32/alloc-id:fake
28914     _Primitive-shift-reg-right-signed-by-lit/imm32/next
28915 _Primitive-shift-reg-right-signed-by-lit:  # (payload primitive)
28916     0x11/imm32/alloc-id:fake:payload
28917     # var1/reg <- shift-right-signed lit => c1/shift 7/subop/right-preserving-sign var1/rm32 lit/imm32
28918     0x11/imm32/alloc-id:fake
28919     _string-shift-right-signed/imm32/name
28920     0x11/imm32/alloc-id:fake
28921     Single-lit-var/imm32/inouts
28922     0x11/imm32/alloc-id:fake
28923     Single-int-var-in-some-register/imm32/outputs
28924     0x11/imm32/alloc-id:fake
28925     _string_c1_subop_shift_right_preserving_sign/imm32/subx-name
28926     3/imm32/rm32-is-first-output
28927     0/imm32/no-r32
28928     0/imm32/no-imm32
28929     1/imm32/imm8-is-first-inout
28930     0/imm32/no-disp32
28931     0/imm32/no-xm32
28932     0/imm32/no-x32
28933     0x11/imm32/alloc-id:fake
28934     _Primitive-shift-mem-left-by-lit/imm32/next
28935 _Primitive-shift-mem-left-by-lit:  # (payload primitive)
28936     0x11/imm32/alloc-id:fake:payload
28937     # shift-left var1, lit => c1/shift 4/subop/left var1/rm32 lit/imm32
28938     0x11/imm32/alloc-id:fake
28939     _string-shift-left/imm32/name
28940     0x11/imm32/alloc-id:fake
28941     Int-var-and-literal/imm32/inouts
28942     0/imm32/no-outputs
28943     0/imm32/no-outputs
28944     0x11/imm32/alloc-id:fake
28945     _string_c1_subop_shift_left/imm32/subx-name
28946     1/imm32/rm32-is-first-inout
28947     0/imm32/no-r32
28948     0/imm32/no-imm32
28949     2/imm32/imm8-is-second-inout
28950     0/imm32/no-disp32
28951     0/imm32/no-xm32
28952     0/imm32/no-x32
28953     0x11/imm32/alloc-id:fake
28954     _Primitive-shift-mem-right-by-lit/imm32/next
28955 _Primitive-shift-mem-right-by-lit:  # (payload primitive)
28956     0x11/imm32/alloc-id:fake:payload
28957     # shift-right var1, lit => c1/shift 5/subop/right var1/rm32 lit/imm32
28958     0x11/imm32/alloc-id:fake
28959     _string-shift-right/imm32/name
28960     0x11/imm32/alloc-id:fake
28961     Int-var-and-literal/imm32/inouts
28962     0/imm32/no-outputs
28963     0/imm32/no-outputs
28964     0x11/imm32/alloc-id:fake
28965     _string_c1_subop_shift_right_padding_zeroes/imm32/subx-name
28966     1/imm32/rm32-is-first-inout
28967     0/imm32/no-r32
28968     0/imm32/no-imm32
28969     2/imm32/imm8-is-second-inout
28970     0/imm32/no-disp32
28971     0/imm32/no-xm32
28972     0/imm32/no-x32
28973     0x11/imm32/alloc-id:fake
28974     _Primitive-shift-mem-right-signed-by-lit/imm32/next
28975 _Primitive-shift-mem-right-signed-by-lit:  # (payload primitive)
28976     0x11/imm32/alloc-id:fake:payload
28977     # shift-right-signed var1, lit => c1/shift 7/subop/right-preserving-sign var1/rm32 lit/imm32
28978     0x11/imm32/alloc-id:fake
28979     _string-shift-right-signed/imm32/name
28980     0x11/imm32/alloc-id:fake
28981     Int-var-and-literal/imm32/inouts
28982     0/imm32/no-outputs
28983     0/imm32/no-outputs
28984     0x11/imm32/alloc-id:fake
28985     _string_c1_subop_shift_right_preserving_sign/imm32/subx-name
28986     1/imm32/rm32-is-first-inout
28987     0/imm32/no-r32
28988     0/imm32/no-imm32
28989     2/imm32/imm8-is-second-inout
28990     0/imm32/no-disp32
28991     0/imm32/no-xm32
28992     0/imm32/no-x32
28993     0x11/imm32/alloc-id:fake
28994     _Primitive-copy-to-eax/imm32/next
28995 # - copy
28996 _Primitive-copy-to-eax:  # (payload primitive)
28997     0x11/imm32/alloc-id:fake:payload
28998     # var/eax <- copy lit => b8/copy-to-eax lit/imm32
28999     0x11/imm32/alloc-id:fake
29000     _string-copy/imm32/name
29001     0x11/imm32/alloc-id:fake
29002     Single-lit-var/imm32/inouts
29003     0x11/imm32/alloc-id:fake
29004     Single-int-var-in-eax/imm32/outputs
29005     0x11/imm32/alloc-id:fake
29006     _string_b8_copy_to_eax/imm32/subx-name
29007     0/imm32/no-rm32
29008     0/imm32/no-r32
29009     1/imm32/imm32-is-first-inout
29010     0/imm32/no-imm8
29011     0/imm32/no-disp32
29012     0/imm32/no-xm32
29013     0/imm32/no-x32
29014     0x11/imm32/alloc-id:fake
29015     _Primitive-copy-to-ecx/imm32/next
29016 _Primitive-copy-to-ecx:  # (payload primitive)
29017     0x11/imm32/alloc-id:fake:payload
29018     # var/ecx <- copy lit => b9/copy-to-ecx lit/imm32
29019     0x11/imm32/alloc-id:fake
29020     _string-copy/imm32/name
29021     0x11/imm32/alloc-id:fake
29022     Single-lit-var/imm32/inouts
29023     0x11/imm32/alloc-id:fake
29024     Single-int-var-in-ecx/imm32/outputs
29025     0x11/imm32/alloc-id:fake
29026     _string_b9_copy_to_ecx/imm32/subx-name
29027     0/imm32/no-rm32
29028     0/imm32/no-r32
29029     1/imm32/imm32-is-first-inout
29030     0/imm32/no-imm8
29031     0/imm32/no-disp32
29032     0/imm32/no-xm32
29033     0/imm32/no-x32
29034     0x11/imm32/alloc-id:fake
29035     _Primitive-copy-to-edx/imm32/next
29036 _Primitive-copy-to-edx:  # (payload primitive)
29037     0x11/imm32/alloc-id:fake:payload
29038     # var/edx <- copy lit => ba/copy-to-edx lit/imm32
29039     0x11/imm32/alloc-id:fake
29040     _string-copy/imm32/name
29041     0x11/imm32/alloc-id:fake
29042     Single-lit-var/imm32/inouts
29043     0x11/imm32/alloc-id:fake
29044     Single-int-var-in-edx/imm32/outputs
29045     0x11/imm32/alloc-id:fake
29046     _string_ba_copy_to_edx/imm32/subx-name
29047     0/imm32/no-rm32
29048     0/imm32/no-r32
29049     1/imm32/imm32-is-first-inout
29050     0/imm32/no-imm8
29051     0/imm32/no-disp32
29052     0/imm32/no-xm32
29053     0/imm32/no-x32
29054     0x11/imm32/alloc-id:fake
29055     _Primitive-copy-to-ebx/imm32/next
29056 _Primitive-copy-to-ebx:  # (payload primitive)
29057     0x11/imm32/alloc-id:fake:payload
29058     # var/ebx <- copy lit => bb/copy-to-ebx lit/imm32
29059     0x11/imm32/alloc-id:fake
29060     _string-copy/imm32/name
29061     0x11/imm32/alloc-id:fake
29062     Single-lit-var/imm32/inouts
29063     0x11/imm32/alloc-id:fake
29064     Single-int-var-in-ebx/imm32/outputs
29065     0x11/imm32/alloc-id:fake
29066     _string_bb_copy_to_ebx/imm32/subx-name
29067     0/imm32/no-rm32
29068     0/imm32/no-r32
29069     1/imm32/imm32-is-first-inout
29070     0/imm32/no-imm8
29071     0/imm32/no-disp32
29072     0/imm32/no-xm32
29073     0/imm32/no-x32
29074     0x11/imm32/alloc-id:fake
29075     _Primitive-copy-to-esi/imm32/next
29076 _Primitive-copy-to-esi:  # (payload primitive)
29077     0x11/imm32/alloc-id:fake:payload
29078     # var/esi <- copy lit => be/copy-to-esi lit/imm32
29079     0x11/imm32/alloc-id:fake
29080     _string-copy/imm32/name
29081     0x11/imm32/alloc-id:fake
29082     Single-lit-var/imm32/inouts
29083     0x11/imm32/alloc-id:fake
29084     Single-int-var-in-esi/imm32/outputs
29085     0x11/imm32/alloc-id:fake
29086     _string_be_copy_to_esi/imm32/subx-name
29087     0/imm32/no-rm32
29088     0/imm32/no-r32
29089     1/imm32/imm32-is-first-inout
29090     0/imm32/no-imm8
29091     0/imm32/no-disp32
29092     0/imm32/no-xm32
29093     0/imm32/no-x32
29094     0x11/imm32/alloc-id:fake
29095     _Primitive-copy-to-edi/imm32/next
29096 _Primitive-copy-to-edi:  # (payload primitive)
29097     0x11/imm32/alloc-id:fake:payload
29098     # var/edi <- copy lit => bf/copy-to-edi lit/imm32
29099     0x11/imm32/alloc-id:fake
29100     _string-copy/imm32/name
29101     0x11/imm32/alloc-id:fake
29102     Single-lit-var/imm32/inouts
29103     0x11/imm32/alloc-id:fake
29104     Single-int-var-in-edi/imm32/outputs
29105     0x11/imm32/alloc-id:fake
29106     _string_bf_copy_to_edi/imm32/subx-name
29107     0/imm32/no-rm32
29108     0/imm32/no-r32
29109     1/imm32/imm32-is-first-inout
29110     0/imm32/no-imm8
29111     0/imm32/no-disp32
29112     0/imm32/no-xm32
29113     0/imm32/no-x32
29114     0x11/imm32/alloc-id:fake
29115     _Primitive-copy-reg-to-reg/imm32/next
29116 _Primitive-copy-reg-to-reg:  # (payload primitive)
29117     0x11/imm32/alloc-id:fake:payload
29118     # var1/reg <- copy var2/reg => 89/<- var1/rm32 var2/r32
29119     0x11/imm32/alloc-id:fake
29120     _string-copy/imm32/name
29121     0x11/imm32/alloc-id:fake
29122     Single-int-var-in-some-register/imm32/inouts
29123     0x11/imm32/alloc-id:fake
29124     Single-int-var-in-some-register/imm32/outputs
29125     0x11/imm32/alloc-id:fake
29126     _string_89_<-/imm32/subx-name
29127     3/imm32/rm32-is-first-output
29128     1/imm32/r32-is-first-inout
29129     0/imm32/no-imm32
29130     0/imm32/no-imm8
29131     0/imm32/no-disp32
29132     0/imm32/no-xm32
29133     0/imm32/no-x32
29134     0x11/imm32/alloc-id:fake
29135     _Primitive-copy-reg-to-mem/imm32/next
29136 _Primitive-copy-reg-to-mem:  # (payload primitive)
29137     0x11/imm32/alloc-id:fake:payload
29138     # copy-to var1 var2/reg => 89/<- var1 var2/r32
29139     0x11/imm32/alloc-id:fake
29140     _string-copy-to/imm32/name
29141     0x11/imm32/alloc-id:fake
29142     Two-args-int-stack-int-reg/imm32/inouts
29143     0/imm32/no-outputs
29144     0/imm32/no-outputs
29145     0x11/imm32/alloc-id:fake
29146     _string_89_<-/imm32/subx-name
29147     1/imm32/rm32-is-first-inout
29148     2/imm32/r32-is-second-inout
29149     0/imm32/no-imm32
29150     0/imm32/no-imm8
29151     0/imm32/no-disp32
29152     0/imm32/no-xm32
29153     0/imm32/no-x32
29154     0x11/imm32/alloc-id:fake
29155     _Primitive-copy-mem-to-reg/imm32/next
29156 _Primitive-copy-mem-to-reg:  # (payload primitive)
29157     0x11/imm32/alloc-id:fake:payload
29158     # var1/reg <- copy var2 => 8b/-> var2/rm32 var1/r32
29159     0x11/imm32/alloc-id:fake
29160     _string-copy/imm32/name
29161     0x11/imm32/alloc-id:fake
29162     Single-int-var-in-mem/imm32/inouts
29163     0x11/imm32/alloc-id:fake
29164     Single-int-var-in-some-register/imm32/outputs
29165     0x11/imm32/alloc-id:fake
29166     _string_8b_->/imm32/subx-name
29167     1/imm32/rm32-is-first-inout
29168     3/imm32/r32-is-first-output
29169     0/imm32/no-imm32
29170     0/imm32/no-imm8
29171     0/imm32/no-disp32
29172     0/imm32/no-xm32
29173     0/imm32/no-x32
29174     0x11/imm32/alloc-id:fake
29175     _Primitive-copy-lit-to-reg/imm32/next
29176 _Primitive-copy-lit-to-reg:  # (payload primitive)
29177     0x11/imm32/alloc-id:fake:payload
29178     # var1/reg <- copy lit => c7 0/subop/copy var1/rm32 lit/imm32
29179     0x11/imm32/alloc-id:fake
29180     _string-copy/imm32/name
29181     0x11/imm32/alloc-id:fake
29182     Single-lit-var/imm32/inouts
29183     0x11/imm32/alloc-id:fake
29184     Single-int-var-in-some-register/imm32/outputs
29185     0x11/imm32/alloc-id:fake
29186     _string_c7_subop_copy/imm32/subx-name
29187     3/imm32/rm32-is-first-output
29188     0/imm32/no-r32
29189     1/imm32/imm32-is-first-inout
29190     0/imm32/no-imm8
29191     0/imm32/no-disp32
29192     0/imm32/no-xm32
29193     0/imm32/no-x32
29194     0x11/imm32/alloc-id:fake
29195     _Primitive-copy-lit-to-mem/imm32/next
29196 _Primitive-copy-lit-to-mem:  # (payload primitive)
29197     0x11/imm32/alloc-id:fake:payload
29198     # copy-to var1, lit => c7 0/subop/copy var1/rm32 lit/imm32
29199     0x11/imm32/alloc-id:fake
29200     _string-copy-to/imm32/name
29201     0x11/imm32/alloc-id:fake
29202     Int-var-and-literal/imm32/inouts
29203     0/imm32/no-outputs
29204     0/imm32/no-outputs
29205     0x11/imm32/alloc-id:fake
29206     _string_c7_subop_copy/imm32/subx-name
29207     1/imm32/rm32-is-first-inout
29208     0/imm32/no-r32
29209     2/imm32/imm32-is-second-inout
29210     0/imm32/no-imm8
29211     0/imm32/no-disp32
29212     0/imm32/no-xm32
29213     0/imm32/no-x32
29214     0x11/imm32/alloc-id:fake
29215     _Primitive-copy-byte-from-reg/imm32/next
29216 # - copy byte
29217 _Primitive-copy-byte-from-reg:
29218     0x11/imm32/alloc-id:fake:payload
29219     # var/reg <- copy-byte var2/reg2 => 8a/byte-> %var2 var/r32
29220     0x11/imm32/alloc-id:fake
29221     _string-copy-byte/imm32/name
29222     0x11/imm32/alloc-id:fake
29223     Single-byte-var-in-some-register/imm32/inouts
29224     0x11/imm32/alloc-id:fake
29225     Single-byte-var-in-some-register/imm32/outputs
29226     0x11/imm32/alloc-id:fake
29227     _string_8a_copy_byte/imm32/subx-name
29228     1/imm32/rm32-is-first-inout
29229     3/imm32/r32-is-first-output
29230     0/imm32/no-imm32
29231     0/imm32/no-imm8
29232     0/imm32/no-disp32
29233     0/imm32/no-xm32
29234     0/imm32/no-x32
29235     0x11/imm32/alloc-id:fake
29236     _Primitive-copy-byte-from-mem/imm32/next
29237 _Primitive-copy-byte-from-mem:
29238     0x11/imm32/alloc-id:fake:payload
29239     # var/reg <- copy-byte *var2/reg2 => 8a/byte-> *var2 var/r32
29240     0x11/imm32/alloc-id:fake
29241     _string-copy-byte/imm32/name
29242     0x11/imm32/alloc-id:fake
29243     Single-byte-var-in-mem/imm32/inouts
29244     0x11/imm32/alloc-id:fake
29245     Single-byte-var-in-some-register/imm32/outputs
29246     0x11/imm32/alloc-id:fake
29247     _string_8a_copy_byte/imm32/subx-name
29248     1/imm32/rm32-is-first-inout
29249     3/imm32/r32-is-first-output
29250     0/imm32/no-imm32
29251     0/imm32/no-imm8
29252     0/imm32/no-disp32
29253     0/imm32/no-xm32
29254     0/imm32/no-x32
29255     0x11/imm32/alloc-id:fake
29256     _Primitive-copy-byte-to-mem/imm32/next
29257 _Primitive-copy-byte-to-mem:
29258     0x11/imm32/alloc-id:fake:payload
29259     # copy-byte-to *var1/reg1, var2/reg2 => 88/byte<- *reg1 reg2/r32
29260     0x11/imm32/alloc-id:fake
29261     _string-copy-byte-to/imm32/name
29262     0x11/imm32/alloc-id:fake
29263     Two-args-byte-stack-byte-reg/imm32/inouts
29264     0/imm32/no-outputs
29265     0/imm32/no-outputs
29266     0x11/imm32/alloc-id:fake
29267     _string_88_copy_byte/imm32/subx-name
29268     1/imm32/rm32-is-first-inout
29269     2/imm32/r32-is-second-inout
29270     0/imm32/no-imm32
29271     0/imm32/no-imm8
29272     0/imm32/no-disp32
29273     0/imm32/no-xm32
29274     0/imm32/no-x32
29275     0x11/imm32/alloc-id:fake
29276     _Primitive-address/imm32/next
29277 # - address
29278 _Primitive-address:  # (payload primitive)
29279     0x11/imm32/alloc-id:fake:payload
29280     # var1/reg <- address var2 => 8d/copy-address var2/rm32 var1/r32
29281     0x11/imm32/alloc-id:fake
29282     _string-address/imm32/name
29283     0x11/imm32/alloc-id:fake
29284     Single-int-var-in-mem/imm32/inouts
29285     0x11/imm32/alloc-id:fake
29286     Single-addr-var-in-some-register/imm32/outputs
29287     0x11/imm32/alloc-id:fake
29288     _string_8d_copy_address/imm32/subx-name
29289     1/imm32/rm32-is-first-inout
29290     3/imm32/r32-is-first-output
29291     0/imm32/no-imm32
29292     0/imm32/no-imm8
29293     0/imm32/no-disp32
29294     0/imm32/no-xm32
29295     0/imm32/no-x32
29296     0x11/imm32/alloc-id:fake
29297     _Primitive-compare-reg-with-reg/imm32/next
29298 # - compare
29299 _Primitive-compare-reg-with-reg:  # (payload primitive)
29300     0x11/imm32/alloc-id:fake:payload
29301     # compare var1/reg1 var2/reg2 => 39/compare var1/rm32 var2/r32
29302     0x11/imm32/alloc-id:fake
29303     _string-compare/imm32/name
29304     0x11/imm32/alloc-id:fake
29305     Two-int-args-in-regs/imm32/inouts
29306     0/imm32/no-outputs
29307     0/imm32/no-outputs
29308     0x11/imm32/alloc-id:fake
29309     _string_39_compare->/imm32/subx-name
29310     1/imm32/rm32-is-first-inout
29311     2/imm32/r32-is-second-inout
29312     0/imm32/no-imm32
29313     0/imm32/no-imm8
29314     0/imm32/no-disp32
29315     0/imm32/no-xm32
29316     0/imm32/no-x32
29317     0x11/imm32/alloc-id:fake
29318     _Primitive-compare-mem-with-reg/imm32/next
29319 _Primitive-compare-mem-with-reg:  # (payload primitive)
29320     0x11/imm32/alloc-id:fake:payload
29321     # compare var1 var2/reg => 39/compare var1/rm32 var2/r32
29322     0x11/imm32/alloc-id:fake
29323     _string-compare/imm32/name
29324     0x11/imm32/alloc-id:fake
29325     Two-args-int-stack-int-reg/imm32/inouts
29326     0/imm32/no-outputs
29327     0/imm32/no-outputs
29328     0x11/imm32/alloc-id:fake
29329     _string_39_compare->/imm32/subx-name
29330     1/imm32/rm32-is-first-inout
29331     2/imm32/r32-is-second-inout
29332     0/imm32/no-imm32
29333     0/imm32/no-imm8
29334     0/imm32/no-disp32
29335     0/imm32/no-xm32
29336     0/imm32/no-x32
29337     0x11/imm32/alloc-id:fake
29338     _Primitive-compare-reg-with-mem/imm32/next
29339 _Primitive-compare-reg-with-mem:  # (payload primitive)
29340     0x11/imm32/alloc-id:fake:payload
29341     # compare var1/reg var2 => 3b/compare<- var2/rm32 var1/r32
29342     0x11/imm32/alloc-id:fake
29343     _string-compare/imm32/name
29344     0x11/imm32/alloc-id:fake
29345     Two-args-int-reg-int-stack/imm32/inouts
29346     0/imm32/no-outputs
29347     0/imm32/no-outputs
29348     0x11/imm32/alloc-id:fake
29349     _string_3b_compare<-/imm32/subx-name
29350     2/imm32/rm32-is-second-inout
29351     1/imm32/r32-is-first-inout
29352     0/imm32/no-imm32
29353     0/imm32/no-imm8
29354     0/imm32/no-disp32
29355     0/imm32/no-xm32
29356     0/imm32/no-x32
29357     0x11/imm32/alloc-id:fake
29358     _Primitive-compare-eax-with-literal/imm32/next
29359 _Primitive-compare-eax-with-literal:  # (payload primitive)
29360     0x11/imm32/alloc-id:fake:payload
29361     # compare var1/eax n => 3d/compare-eax-with n/imm32
29362     0x11/imm32/alloc-id:fake
29363     _string-compare/imm32/name
29364     0x11/imm32/alloc-id:fake
29365     Two-args-int-eax-int-literal/imm32/inouts
29366     0/imm32/no-outputs
29367     0/imm32/no-outputs
29368     0x11/imm32/alloc-id:fake
29369     _string_3d_compare_eax_with/imm32/subx-name
29370     0/imm32/no-rm32
29371     0/imm32/no-r32
29372     2/imm32/imm32-is-second-inout
29373     0/imm32/no-imm8
29374     0/imm32/no-disp32
29375     0/imm32/no-xm32
29376     0/imm32/no-x32
29377     0x11/imm32/alloc-id:fake
29378     _Primitive-compare-reg-with-literal/imm32/next
29379 _Primitive-compare-reg-with-literal:  # (payload primitive)
29380     0x11/imm32/alloc-id:fake:payload
29381     # compare var1/reg n => 81 7/subop/compare %reg n/imm32
29382     0x11/imm32/alloc-id:fake
29383     _string-compare/imm32/name
29384     0x11/imm32/alloc-id:fake
29385     Int-var-in-register-and-literal/imm32/inouts
29386     0/imm32/no-outputs
29387     0/imm32/no-outputs
29388     0x11/imm32/alloc-id:fake
29389     _string_81_subop_compare/imm32/subx-name
29390     1/imm32/rm32-is-first-inout
29391     0/imm32/no-r32
29392     2/imm32/imm32-is-second-inout
29393     0/imm32/no-imm8
29394     0/imm32/no-disp32
29395     0/imm32/no-xm32
29396     0/imm32/no-x32
29397     0x11/imm32/alloc-id:fake
29398     _Primitive-compare-mem-with-literal/imm32/next
29399 _Primitive-compare-mem-with-literal:  # (payload primitive)
29400     0x11/imm32/alloc-id:fake:payload
29401     # compare var1 n => 81 7/subop/compare *(ebp+___) n/imm32
29402     0x11/imm32/alloc-id:fake
29403     _string-compare/imm32/name
29404     0x11/imm32/alloc-id:fake
29405     Int-var-and-literal/imm32/inouts
29406     0/imm32/no-outputs
29407     0/imm32/no-outputs
29408     0x11/imm32/alloc-id:fake
29409     _string_81_subop_compare/imm32/subx-name
29410     1/imm32/rm32-is-first-inout
29411     0/imm32/no-r32
29412     2/imm32/imm32-is-second-inout
29413     0/imm32/no-imm8
29414     0/imm32/no-disp32
29415     0/imm32/no-xm32
29416     0/imm32/no-x32
29417     0x11/imm32/alloc-id:fake
29418     _Primitive-negate-reg/imm32/next
29419 # - negate
29420 _Primitive-negate-reg:  # (payload primitive)
29421     0x11/imm32/alloc-id:fake:payload
29422     # var1/reg <- negate => f7 3/subop/negate var1/rm32
29423     0x11/imm32/alloc-id:fake
29424     _string-negate/imm32/name
29425     0/imm32/no-inouts
29426     0/imm32/no-inouts
29427     0x11/imm32/alloc-id:fake
29428     Single-int-var-in-some-register/imm32/outputs
29429     0x11/imm32/alloc-id:fake
29430     _string_f7_subop_negate/imm32/subx-name
29431     3/imm32/rm32-is-first-output
29432     0/imm32/no-r32
29433     0/imm32/no-imm32
29434     0/imm32/no-imm8
29435     0/imm32/no-disp32
29436     0/imm32/no-xm32
29437     0/imm32/no-x32
29438     0x11/imm32/alloc-id:fake
29439     _Primitive-negate-mem/imm32/next
29440 _Primitive-negate-mem:  # (payload primitive)
29441     0x11/imm32/alloc-id:fake:payload
29442     # negate var1 => f7 3/subop/negate var1/rm32
29443     0x11/imm32/alloc-id:fake
29444     _string-negate/imm32/name
29445     0x11/imm32/alloc-id:fake
29446     Single-int-var-in-mem/imm32/inouts
29447     0/imm32/no-outputs
29448     0/imm32/no-outputs
29449     0x11/imm32/alloc-id:fake
29450     _string_f7_subop_negate/imm32/subx-name
29451     1/imm32/rm32-is-first-inout
29452     0/imm32/no-r32
29453     0/imm32/no-imm32
29454     0/imm32/no-imm8
29455     0/imm32/no-disp32
29456     0/imm32/no-xm32
29457     0/imm32/no-x32
29458     0x11/imm32/alloc-id:fake
29459     _Primitive-multiply-reg-by-reg/imm32/next
29460 # - multiply
29461 _Primitive-multiply-reg-by-reg:  # (payload primitive)
29462     0x11/imm32/alloc-id:fake:payload
29463     # var1/reg <- multiply var2 => 0f af/multiply var2/rm32 var1/r32
29464     0x11/imm32/alloc-id:fake
29465     _string-multiply/imm32/name
29466     0x11/imm32/alloc-id:fake
29467     Single-int-var-in-some-register/imm32/inouts
29468     0x11/imm32/alloc-id:fake
29469     Single-int-var-in-some-register/imm32/outputs
29470     0x11/imm32/alloc-id:fake
29471     _string_0f_af_multiply/imm32/subx-name
29472     1/imm32/rm32-is-first-inout
29473     3/imm32/r32-is-first-output
29474     0/imm32/no-imm32
29475     0/imm32/no-imm8
29476     0/imm32/no-disp32
29477     0/imm32/no-xm32
29478     0/imm32/no-x32
29479     0x11/imm32/alloc-id:fake
29480     _Primitive-multiply-reg-by-mem/imm32/next
29481 _Primitive-multiply-reg-by-mem:  # (payload primitive)
29482     0x11/imm32/alloc-id:fake:payload
29483     # var1/reg <- multiply var2 => 0f af/multiply var2/rm32 var1/r32
29484     0x11/imm32/alloc-id:fake
29485     _string-multiply/imm32/name
29486     0x11/imm32/alloc-id:fake
29487     Single-int-var-in-mem/imm32/inouts
29488     0x11/imm32/alloc-id:fake
29489     Single-int-var-in-some-register/imm32/outputs
29490     0x11/imm32/alloc-id:fake
29491     _string_0f_af_multiply/imm32/subx-name
29492     1/imm32/rm32-is-first-inout
29493     3/imm32/r32-is-first-output
29494     0/imm32/no-imm32
29495     0/imm32/no-imm8
29496     0/imm32/no-disp32
29497     0/imm32/no-xm32
29498     0/imm32/no-x32
29499     0x11/imm32/alloc-id:fake
29500     _Primitive-convert-mem-to-xreg/imm32/next
29501 # - convert int to floating point
29502 _Primitive-convert-mem-to-xreg:  # (payload primitive)
29503     0x11/imm32/alloc-id:fake:payload
29504     # var1/xreg <- convert var2 => f3 0f 2a/convert-to-float var2/rm32 var1/x32
29505     0x11/imm32/alloc-id:fake
29506     _string-convert/imm32/name
29507     0x11/imm32/alloc-id:fake
29508     Single-int-var-in-mem/imm32/inouts
29509     0x11/imm32/alloc-id:fake
29510     Single-float-var-in-some-register/imm32/outputs
29511     0x11/imm32/alloc-id:fake
29512     _string_f3_0f_2a_convert_to_float/imm32/subx-name
29513     1/imm32/rm32-is-first-inout
29514     0/imm32/no-r32
29515     0/imm32/no-imm32
29516     0/imm32/no-imm8
29517     0/imm32/no-disp32
29518     0/imm32/no-xm32
29519     3/imm32/x32-is-first-output
29520     0x11/imm32/alloc-id:fake
29521     _Primitive-convert-reg-to-xreg/imm32/next
29522 _Primitive-convert-reg-to-xreg:  # (payload primitive)
29523     0x11/imm32/alloc-id:fake:payload
29524     # var1/xreg <- convert var2/reg => f3 0f 2a/convert-to-float var2/rm32 var1/x32
29525     0x11/imm32/alloc-id:fake
29526     _string-convert/imm32/name
29527     0x11/imm32/alloc-id:fake
29528     Single-int-var-in-some-register/imm32/inouts
29529     0x11/imm32/alloc-id:fake
29530     Single-float-var-in-some-register/imm32/outputs
29531     0x11/imm32/alloc-id:fake
29532     _string_f3_0f_2a_convert_to_float/imm32/subx-name
29533     1/imm32/rm32-is-first-inout
29534     0/imm32/no-r32
29535     0/imm32/no-imm32
29536     0/imm32/no-imm8
29537     0/imm32/no-disp32
29538     0/imm32/no-xm32
29539     3/imm32/x32-is-first-output
29540     0x11/imm32/alloc-id:fake
29541     _Primitive-convert-xmem-to-reg/imm32/next
29542 # - convert floating point to int
29543 _Primitive-convert-xmem-to-reg:  # (payload primitive)
29544     0x11/imm32/alloc-id:fake:payload
29545     # var1/reg <- convert var2 => f3 0f 2d/convert-to-int var2/xm32 var1/r32
29546     0x11/imm32/alloc-id:fake
29547     _string-convert/imm32/name
29548     0x11/imm32/alloc-id:fake
29549     Single-float-var-in-mem/imm32/inouts
29550     0x11/imm32/alloc-id:fake
29551     Single-int-var-in-some-register/imm32/outputs
29552     0x11/imm32/alloc-id:fake
29553     _string_f3_0f_2d_convert_to_int/imm32/subx-name
29554     0/imm32/no-rm32
29555     3/imm32/r32-is-first-output
29556     0/imm32/no-imm32
29557     0/imm32/no-imm8
29558     0/imm32/no-disp32
29559     1/imm32/xm32-is-first-inout
29560     0/imm32/no-x32
29561     0x11/imm32/alloc-id:fake
29562     _Primitive-convert-xreg-to-reg/imm32/next
29563 _Primitive-convert-xreg-to-reg:  # (payload primitive)
29564     0x11/imm32/alloc-id:fake:payload
29565     # var1/reg <- convert var2/xreg => f3 0f 2d/convert-to-int var2/xm32 var1/r32
29566     0x11/imm32/alloc-id:fake
29567     _string-convert/imm32/name
29568     0x11/imm32/alloc-id:fake
29569     Single-float-var-in-some-register/imm32/inouts
29570     0x11/imm32/alloc-id:fake
29571     Single-int-var-in-some-register/imm32/outputs
29572     0x11/imm32/alloc-id:fake
29573     _string_f3_0f_2d_convert_to_int/imm32/subx-name
29574     0/imm32/no-rm32
29575     3/imm32/r32-is-first-output
29576     0/imm32/no-imm32
29577     0/imm32/no-imm8
29578     0/imm32/no-disp32
29579     1/imm32/xm32-is-first-inout
29580     0/imm32/no-x32
29581     0x11/imm32/alloc-id:fake
29582     _Primitive-truncate-xmem-to-reg/imm32/next
29583 _Primitive-truncate-xmem-to-reg:  # (payload primitive)
29584     0x11/imm32/alloc-id:fake:payload
29585     # var1/reg <- truncate var2 => f3 0f 2c/truncate-to-int var2/xm32 var1/r32
29586     0x11/imm32/alloc-id:fake
29587     _string-truncate/imm32/name
29588     0x11/imm32/alloc-id:fake
29589     Single-float-var-in-mem/imm32/inouts
29590     0x11/imm32/alloc-id:fake
29591     Single-int-var-in-some-register/imm32/outputs
29592     0x11/imm32/alloc-id:fake
29593     _string_f3_0f_2c_truncate_to_int/imm32/subx-name
29594     0/imm32/no-rm32
29595     3/imm32/r32-is-first-output
29596     0/imm32/no-imm32
29597     0/imm32/no-imm8
29598     0/imm32/no-disp32
29599     1/imm32/xm32-is-first-inout
29600     0/imm32/no-x32
29601     0x11/imm32/alloc-id:fake
29602     _Primitive-truncate-xreg-to-reg/imm32/next
29603 _Primitive-truncate-xreg-to-reg:  # (payload primitive)
29604     0x11/imm32/alloc-id:fake:payload
29605     # var1/reg <- truncate var2/xreg => f3 0f 2c/truncate-to-int var2/xm32 var1/r32
29606     0x11/imm32/alloc-id:fake
29607     _string-truncate/imm32/name
29608     0x11/imm32/alloc-id:fake
29609     Single-float-var-in-some-register/imm32/inouts
29610     0x11/imm32/alloc-id:fake
29611     Single-int-var-in-some-register/imm32/outputs
29612     0x11/imm32/alloc-id:fake
29613     _string_f3_0f_2c_truncate_to_int/imm32/subx-name
29614     0/imm32/no-rm32
29615     3/imm32/r32-is-first-output
29616     0/imm32/no-imm32
29617     0/imm32/no-imm8
29618     0/imm32/no-disp32
29619     1/imm32/xm32-is-first-inout
29620     0/imm32/no-x32
29621     0x11/imm32/alloc-id:fake
29622     _Primitive-reinterpret-xmem-as-reg/imm32/next
29623 # - reinterpret bytes (just for debugging)
29624 _Primitive-reinterpret-xmem-as-reg:  # (payload primitive)
29625     0x11/imm32/alloc-id:fake:payload
29626     # var1/reg <- reinterpret var2 => 8b/-> var2/xm32 var1/r32
29627     0x11/imm32/alloc-id:fake
29628     _string-reinterpret/imm32/name
29629     0x11/imm32/alloc-id:fake
29630     Single-float-var-in-mem/imm32/inouts
29631     0x11/imm32/alloc-id:fake
29632     Single-int-var-in-some-register/imm32/outputs
29633     0x11/imm32/alloc-id:fake
29634     _string_8b_->/imm32/subx-name
29635     0/imm32/no-rm32
29636     3/imm32/r32-is-first-output
29637     0/imm32/no-imm32
29638     0/imm32/no-imm8
29639     0/imm32/no-disp32
29640     1/imm32/xm32-is-first-inout
29641     0/imm32/no-x32
29642     0x11/imm32/alloc-id:fake
29643     _Primitive-reinterpret-mem-as-xreg/imm32/next
29644 _Primitive-reinterpret-mem-as-xreg:  # (payload primitive)
29645     0x11/imm32/alloc-id:fake:payload
29646     # var1/xreg <- reinterpret var2 => f3 0f 10/-> var2/rm32 var1/x32
29647     0x11/imm32/alloc-id:fake
29648     _string-reinterpret/imm32/name
29649     0x11/imm32/alloc-id:fake
29650     Single-int-var-in-mem/imm32/inouts
29651     0x11/imm32/alloc-id:fake
29652     Single-float-var-in-some-register/imm32/outputs
29653     0x11/imm32/alloc-id:fake
29654     _string_f3_0f_10_copy/imm32/subx-name
29655     1/imm32/rm32-is-first-inout
29656     0/imm32/no-r32
29657     0/imm32/no-imm32
29658     0/imm32/no-imm8
29659     0/imm32/no-disp32
29660     0/imm32/no-xm32
29661     3/imm32/x32-is-first-output
29662     0x11/imm32/alloc-id:fake
29663     _Primitive-copy-xreg-to-xreg/imm32/next
29664 # - floating-point copy
29665 _Primitive-copy-xreg-to-xreg:  # (payload primitive)
29666     0x11/imm32/alloc-id:fake:payload
29667     # var1/xreg <- copy var2/xreg => f3 0f 11/<- var1/xm32 var2/x32
29668     0x11/imm32/alloc-id:fake
29669     _string-copy/imm32/name
29670     0x11/imm32/alloc-id:fake
29671     Single-float-var-in-some-register/imm32/inouts
29672     0x11/imm32/alloc-id:fake
29673     Single-float-var-in-some-register/imm32/outputs
29674     0x11/imm32/alloc-id:fake
29675     _string_f3_0f_11_copy/imm32/subx-name
29676     0/imm32/no-rm32
29677     0/imm32/no-r32
29678     0/imm32/no-imm32
29679     0/imm32/no-imm8
29680     0/imm32/no-disp32
29681     3/imm32/xm32-is-first-output
29682     1/imm32/x32-is-first-inout
29683     0x11/imm32/alloc-id:fake
29684     _Primitive-copy-xreg-to-mem/imm32/next
29685 _Primitive-copy-xreg-to-mem:  # (payload primitive)
29686     0x11/imm32/alloc-id:fake:payload
29687     # copy-to var1 var2/xreg => f3 0f 11/<- var1 var2/x32
29688     0x11/imm32/alloc-id:fake
29689     _string-copy-to/imm32/name
29690     0x11/imm32/alloc-id:fake
29691     Two-args-float-stack-float-reg/imm32/inouts
29692     0/imm32/no-outputs
29693     0/imm32/no-outputs
29694     0x11/imm32/alloc-id:fake
29695     _string_f3_0f_11_copy/imm32/subx-name
29696     0/imm32/no-rm32
29697     0/imm32/no-r32
29698     0/imm32/no-imm32
29699     0/imm32/no-imm8
29700     0/imm32/no-disp32
29701     1/imm32/xm32-is-first-inout
29702     2/imm32/x32-is-second-inout
29703     0x11/imm32/alloc-id:fake
29704     _Primitive-copy-mem-to-xreg/imm32/next
29705 _Primitive-copy-mem-to-xreg:  # (payload primitive)
29706     0x11/imm32/alloc-id:fake:payload
29707     # var1/xreg <- copy var2 => f3 0f 10/-> var2/rm32 var1/x32
29708     0x11/imm32/alloc-id:fake
29709     _string-copy/imm32/name
29710     0x11/imm32/alloc-id:fake
29711     Single-float-var-in-mem/imm32/inouts
29712     0x11/imm32/alloc-id:fake
29713     Single-float-var-in-some-register/imm32/outputs
29714     0x11/imm32/alloc-id:fake
29715     _string_f3_0f_10_copy/imm32/subx-name
29716     0/imm32/no-rm32
29717     0/imm32/no-r32
29718     0/imm32/no-imm32
29719     0/imm32/no-imm8
29720     0/imm32/no-disp32
29721     1/imm32/xm32-is-first-inout
29722     3/imm32/x32-is-first-output
29723     0x11/imm32/alloc-id:fake
29724     _Primitive-address-of-xmem/imm32/next
29725 # - floating-point-address
29726 _Primitive-address-of-xmem:  # (payload primitive)
29727     0x11/imm32/alloc-id:fake:payload
29728     # var1/reg <- address var2 => 8d/copy-address var2/rm32 var1/r32
29729     0x11/imm32/alloc-id:fake
29730     _string-address/imm32/name
29731     0x11/imm32/alloc-id:fake
29732     Single-float-var-in-mem/imm32/inouts
29733     0x11/imm32/alloc-id:fake
29734     Single-addr-var-in-some-register/imm32/outputs
29735     0x11/imm32/alloc-id:fake
29736     _string_8d_copy_address/imm32/subx-name
29737     1/imm32/rm32-is-first-inout
29738     3/imm32/r32-is-first-output
29739     0/imm32/no-imm32
29740     0/imm32/no-imm8
29741     0/imm32/no-disp32
29742     0/imm32/no-xm32
29743     0/imm32/no-x32
29744     0x11/imm32/alloc-id:fake
29745     _Primitive-add-xreg-to-xreg/imm32/next
29746 # - floating-point add
29747 _Primitive-add-xreg-to-xreg:  # (payload primitive)
29748     0x11/imm32/alloc-id:fake:payload
29749     # var1/xreg <- add var2/xreg => f3 0f 58/add var1/xm32 var2/x32
29750     0x11/imm32/alloc-id:fake
29751     _string-add/imm32/name
29752     0x11/imm32/alloc-id:fake
29753     Single-float-var-in-some-register/imm32/inouts
29754     0x11/imm32/alloc-id:fake
29755     Single-float-var-in-some-register/imm32/outputs
29756     0x11/imm32/alloc-id:fake
29757     _string_f3_0f_58_add/imm32/subx-name
29758     0/imm32/no-rm32
29759     0/imm32/no-r32
29760     0/imm32/no-imm32
29761     0/imm32/no-imm8
29762     0/imm32/no-disp32
29763     1/imm32/xm32-is-first-inout
29764     3/imm32/x32-is-first-output
29765     0x11/imm32/alloc-id:fake
29766     _Primitive-add-mem-to-xreg/imm32/next
29767 _Primitive-add-mem-to-xreg:  # (payload primitive)
29768     0x11/imm32/alloc-id:fake:payload
29769     # var1/xreg <- add var2 => f3 0f 58/add var2/xm32 var1/x32
29770     0x11/imm32/alloc-id:fake
29771     _string-add/imm32/name
29772     0x11/imm32/alloc-id:fake
29773     Single-float-var-in-mem/imm32/inouts
29774     0x11/imm32/alloc-id:fake
29775     Single-float-var-in-some-register/imm32/outputs
29776     0x11/imm32/alloc-id:fake
29777     _string_f3_0f_58_add/imm32/subx-name
29778     0/imm32/no-rm32
29779     0/imm32/no-r32
29780     0/imm32/no-imm32
29781     0/imm32/no-imm8
29782     0/imm32/no-disp32
29783     1/imm32/xm32-is-first-inout
29784     3/imm32/x32-is-first-output
29785     0x11/imm32/alloc-id:fake
29786     _Primitive-subtract-xreg-from-xreg/imm32/next
29787 # - floating-point subtract
29788 _Primitive-subtract-xreg-from-xreg:  # (payload primitive)
29789     0x11/imm32/alloc-id:fake:payload
29790     # var1/xreg <- subtract var2/xreg => f3 0f 5c/subtract var1/xm32 var2/x32
29791     0x11/imm32/alloc-id:fake
29792     _string-subtract/imm32/name
29793     0x11/imm32/alloc-id:fake
29794     Single-float-var-in-some-register/imm32/inouts
29795     0x11/imm32/alloc-id:fake
29796     Single-float-var-in-some-register/imm32/outputs
29797     0x11/imm32/alloc-id:fake
29798     _string_f3_0f_5c_subtract/imm32/subx-name
29799     0/imm32/no-rm32
29800     0/imm32/no-r32
29801     0/imm32/no-imm32
29802     0/imm32/no-imm8
29803     0/imm32/no-disp32
29804     1/imm32/xm32-is-first-inout
29805     3/imm32/x32-is-first-output
29806     0x11/imm32/alloc-id:fake
29807     _Primitive-subtract-mem-from-xreg/imm32/next
29808 _Primitive-subtract-mem-from-xreg:  # (payload primitive)
29809     0x11/imm32/alloc-id:fake:payload
29810     # var1/xreg <- subtract var2 => f3 0f 5c/subtract var2/xm32 var1/x32
29811     0x11/imm32/alloc-id:fake
29812     _string-subtract/imm32/name
29813     0x11/imm32/alloc-id:fake
29814     Single-float-var-in-mem/imm32/inouts
29815     0x11/imm32/alloc-id:fake
29816     Single-float-var-in-some-register/imm32/outputs
29817     0x11/imm32/alloc-id:fake
29818     _string_f3_0f_5c_subtract/imm32/subx-name
29819     0/imm32/no-rm32
29820     0/imm32/no-r32
29821     0/imm32/no-imm32
29822     0/imm32/no-imm8
29823     0/imm32/no-disp32
29824     1/imm32/xm32-is-first-inout
29825     3/imm32/x32-is-first-output
29826     0x11/imm32/alloc-id:fake
29827     _Primitive-multiply-xreg-by-xreg/imm32/next
29828 # - floating-point multiply
29829 _Primitive-multiply-xreg-by-xreg:  # (payload primitive)
29830     0x11/imm32/alloc-id:fake:payload
29831     # var1/xreg <- multiply var2 => f3 0f 59/multiply var2/xm32 var1/x32
29832     0x11/imm32/alloc-id:fake
29833     _string-multiply/imm32/name
29834     0x11/imm32/alloc-id:fake
29835     Single-float-var-in-some-register/imm32/inouts
29836     0x11/imm32/alloc-id:fake
29837     Single-float-var-in-some-register/imm32/outputs
29838     0x11/imm32/alloc-id:fake
29839     _string_f3_0f_59_multiply/imm32/subx-name
29840     0/imm32/no-rm32
29841     0/imm32/no-r32
29842     0/imm32/no-imm32
29843     0/imm32/no-imm8
29844     0/imm32/no-disp32
29845     1/imm32/xm32-is-first-inout
29846     3/imm32/x32-is-first-output
29847     0x11/imm32/alloc-id:fake
29848     _Primitive-multiply-xreg-by-mem/imm32/next
29849 _Primitive-multiply-xreg-by-mem:  # (payload primitive)
29850     0x11/imm32/alloc-id:fake:payload
29851     # var1/xreg <- multiply var2 => 53 0f 59/multiply var2/xm32 var1/x32
29852     0x11/imm32/alloc-id:fake
29853     _string-multiply/imm32/name
29854     0x11/imm32/alloc-id:fake
29855     Single-float-var-in-mem/imm32/inouts
29856     0x11/imm32/alloc-id:fake
29857     Single-float-var-in-some-register/imm32/outputs
29858     0x11/imm32/alloc-id:fake
29859     _string_f3_0f_59_multiply/imm32/subx-name
29860     0/imm32/no-rm32
29861     0/imm32/no-r32
29862     0/imm32/no-imm32
29863     0/imm32/no-imm8
29864     0/imm32/no-disp32
29865     1/imm32/xm32-is-first-inout
29866     3/imm32/x32-is-first-output
29867     0x11/imm32/alloc-id:fake
29868     _Primitive-divide-xreg-by-xreg/imm32/next
29869 # - floating-point divide
29870 _Primitive-divide-xreg-by-xreg:  # (payload primitive)
29871     0x11/imm32/alloc-id:fake:payload
29872     # var1/xreg <- divide var2 => f3 0f 5e/divide var2/xm32 var1/x32
29873     0x11/imm32/alloc-id:fake
29874     _string-divide/imm32/name
29875     0x11/imm32/alloc-id:fake
29876     Single-float-var-in-some-register/imm32/inouts
29877     0x11/imm32/alloc-id:fake
29878     Single-float-var-in-some-register/imm32/outputs
29879     0x11/imm32/alloc-id:fake
29880     _string_f3_0f_5e_divide/imm32/subx-name
29881     0/imm32/no-rm32
29882     0/imm32/no-r32
29883     0/imm32/no-imm32
29884     0/imm32/no-imm8
29885     0/imm32/no-disp32
29886     1/imm32/xm32-is-first-inout
29887     3/imm32/x32-is-first-output
29888     0x11/imm32/alloc-id:fake
29889     _Primitive-divide-xreg-by-mem/imm32/next
29890 _Primitive-divide-xreg-by-mem:  # (payload primitive)
29891     0x11/imm32/alloc-id:fake:payload
29892     # var1/xreg <- divide var2 => f3 0f 5e/divide var2/xm32 var1/x32
29893     0x11/imm32/alloc-id:fake
29894     _string-divide/imm32/name
29895     0x11/imm32/alloc-id:fake
29896     Single-float-var-in-mem/imm32/inouts
29897     0x11/imm32/alloc-id:fake
29898     Single-float-var-in-some-register/imm32/outputs
29899     0x11/imm32/alloc-id:fake
29900     _string_f3_0f_5e_divide/imm32/subx-name
29901     0/imm32/no-rm32
29902     0/imm32/no-r32
29903     0/imm32/no-imm32
29904     0/imm32/no-imm8
29905     0/imm32/no-disp32
29906     1/imm32/xm32-is-first-inout
29907     3/imm32/x32-is-first-output
29908     0x11/imm32/alloc-id:fake
29909     _Primitive-max-xreg-with-xreg/imm32/next
29910 # - floating-point maximum
29911 _Primitive-max-xreg-with-xreg:  # (payload primitive)
29912     0x11/imm32/alloc-id:fake:payload
29913     # var1/xreg <- max var2 => f3 0f 5f/max var2/xm32 var1/x32
29914     0x11/imm32/alloc-id:fake
29915     _string-max/imm32/name
29916     0x11/imm32/alloc-id:fake
29917     Single-float-var-in-some-register/imm32/inouts
29918     0x11/imm32/alloc-id:fake
29919     Single-float-var-in-some-register/imm32/outputs
29920     0x11/imm32/alloc-id:fake
29921     _string_f3_0f_5f_max/imm32/subx-name
29922     0/imm32/no-rm32
29923     0/imm32/no-r32
29924     0/imm32/no-imm32
29925     0/imm32/no-imm8
29926     0/imm32/no-disp32
29927     1/imm32/xm32-is-first-inout
29928     3/imm32/x32-is-first-output
29929     0x11/imm32/alloc-id:fake
29930     _Primitive-max-xreg-with-mem/imm32/next
29931 _Primitive-max-xreg-with-mem:  # (payload primitive)
29932     0x11/imm32/alloc-id:fake:payload
29933     # var1/xreg <- divide var2 => f3 0f 5f/max var2/xm32 var1/x32
29934     0x11/imm32/alloc-id:fake
29935     _string-max/imm32/name
29936     0x11/imm32/alloc-id:fake
29937     Single-float-var-in-mem/imm32/inouts
29938     0x11/imm32/alloc-id:fake
29939     Single-float-var-in-some-register/imm32/outputs
29940     0x11/imm32/alloc-id:fake
29941     _string_f3_0f_5f_max/imm32/subx-name
29942     0/imm32/no-rm32
29943     0/imm32/no-r32
29944     0/imm32/no-imm32
29945     0/imm32/no-imm8
29946     0/imm32/no-disp32
29947     1/imm32/xm32-is-first-inout
29948     3/imm32/x32-is-first-output
29949     0x11/imm32/alloc-id:fake
29950     _Primitive-min-xreg-with-xreg/imm32/next
29951 # - floating-point minimum
29952 _Primitive-min-xreg-with-xreg:  # (payload primitive)
29953     0x11/imm32/alloc-id:fake:payload
29954     # var1/xreg <- divide var2 => f3 0f 5d/min var2/xm32 var1/x32
29955     0x11/imm32/alloc-id:fake
29956     _string-min/imm32/name
29957     0x11/imm32/alloc-id:fake
29958     Single-float-var-in-some-register/imm32/inouts
29959     0x11/imm32/alloc-id:fake
29960     Single-float-var-in-some-register/imm32/outputs
29961     0x11/imm32/alloc-id:fake
29962     _string_f3_0f_5d_min/imm32/subx-name
29963     0/imm32/no-rm32
29964     0/imm32/no-r32
29965     0/imm32/no-imm32
29966     0/imm32/no-imm8
29967     0/imm32/no-disp32
29968     1/imm32/xm32-is-first-inout
29969     3/imm32/x32-is-first-output
29970     0x11/imm32/alloc-id:fake
29971     _Primitive-min-xreg-with-mem/imm32/next
29972 _Primitive-min-xreg-with-mem:  # (payload primitive)
29973     0x11/imm32/alloc-id:fake:payload
29974     # var1/xreg <- divide var2 => f3 0f 5d/min var2/xm32 var1/x32
29975     0x11/imm32/alloc-id:fake
29976     _string-min/imm32/name
29977     0x11/imm32/alloc-id:fake
29978     Single-float-var-in-mem/imm32/inouts
29979     0x11/imm32/alloc-id:fake
29980     Single-float-var-in-some-register/imm32/outputs
29981     0x11/imm32/alloc-id:fake
29982     _string_f3_0f_5d_min/imm32/subx-name
29983     0/imm32/no-rm32
29984     0/imm32/no-r32
29985     0/imm32/no-imm32
29986     0/imm32/no-imm8
29987     0/imm32/no-disp32
29988     1/imm32/xm32-is-first-inout
29989     3/imm32/x32-is-first-output
29990     0x11/imm32/alloc-id:fake
29991     _Primitive-reciprocal-xreg-to-xreg/imm32/next
29992 # - floating-point reciprocal
29993 _Primitive-reciprocal-xreg-to-xreg:  # (payload primitive)
29994     0x11/imm32/alloc-id:fake:payload
29995     # var1/xreg <- reciprocal var2 => f3 0f 53/reciprocal var2/xm32 var1/x32
29996     0x11/imm32/alloc-id:fake
29997     _string-reciprocal/imm32/name
29998     0x11/imm32/alloc-id:fake
29999     Single-float-var-in-some-register/imm32/inouts
30000     0x11/imm32/alloc-id:fake
30001     Single-float-var-in-some-register/imm32/outputs
30002     0x11/imm32/alloc-id:fake
30003     _string_f3_0f_53_reciprocal/imm32/subx-name
30004     0/imm32/no-rm32
30005     0/imm32/no-r32
30006     0/imm32/no-imm32
30007     0/imm32/no-imm8
30008     0/imm32/no-disp32
30009     1/imm32/xm32-is-first-inout
30010     3/imm32/x32-is-first-output
30011     0x11/imm32/alloc-id:fake
30012     _Primitive-reciprocal-mem-to-xreg/imm32/next
30013 _Primitive-reciprocal-mem-to-xreg:  # (payload primitive)
30014     0x11/imm32/alloc-id:fake:payload
30015     # var1/xreg <- divide var2 => f3 0f 53/reciprocal var2/xm32 var1/x32
30016     0x11/imm32/alloc-id:fake
30017     _string-reciprocal/imm32/name
30018     0x11/imm32/alloc-id:fake
30019     Single-float-var-in-mem/imm32/inouts
30020     0x11/imm32/alloc-id:fake
30021     Single-float-var-in-some-register/imm32/outputs
30022     0x11/imm32/alloc-id:fake
30023     _string_f3_0f_53_reciprocal/imm32/subx-name
30024     0/imm32/no-rm32
30025     0/imm32/no-r32
30026     0/imm32/no-imm32
30027     0/imm32/no-imm8
30028     0/imm32/no-disp32
30029     1/imm32/xm32-is-first-inout
30030     3/imm32/x32-is-first-output
30031     0x11/imm32/alloc-id:fake
30032     _Primitive-square-root-xreg-to-xreg/imm32/next
30033 # - floating-point square root
30034 _Primitive-square-root-xreg-to-xreg:  # (payload primitive)
30035     0x11/imm32/alloc-id:fake:payload
30036     # var1/xreg <- square-root var2 => f3 0f 51/square-root var2/xm32 var1/x32
30037     0x11/imm32/alloc-id:fake
30038     _string-square-root/imm32/name
30039     0x11/imm32/alloc-id:fake
30040     Single-float-var-in-some-register/imm32/inouts
30041     0x11/imm32/alloc-id:fake
30042     Single-float-var-in-some-register/imm32/outputs
30043     0x11/imm32/alloc-id:fake
30044     _string_f3_0f_51_square_root/imm32/subx-name
30045     0/imm32/no-rm32
30046     0/imm32/no-r32
30047     0/imm32/no-imm32
30048     0/imm32/no-imm8
30049     0/imm32/no-disp32
30050     1/imm32/xm32-is-first-inout
30051     3/imm32/x32-is-first-output
30052     0x11/imm32/alloc-id:fake
30053     _Primitive-square-root-mem-to-xreg/imm32/next
30054 _Primitive-square-root-mem-to-xreg:  # (payload primitive)
30055     0x11/imm32/alloc-id:fake:payload
30056     # var1/xreg <- divide var2 => f3 0f 51/square-root var2/xm32 var1/x32
30057     0x11/imm32/alloc-id:fake
30058     _string-square-root/imm32/name
30059     0x11/imm32/alloc-id:fake
30060     Single-float-var-in-mem/imm32/inouts
30061     0x11/imm32/alloc-id:fake
30062     Single-float-var-in-some-register/imm32/outputs
30063     0x11/imm32/alloc-id:fake
30064     _string_f3_0f_51_square_root/imm32/subx-name
30065     0/imm32/no-rm32
30066     0/imm32/no-r32
30067     0/imm32/no-imm32
30068     0/imm32/no-imm8
30069     0/imm32/no-disp32
30070     1/imm32/xm32-is-first-inout
30071     3/imm32/x32-is-first-output
30072     0x11/imm32/alloc-id:fake
30073     _Primitive-inverse-square-root-xreg-to-xreg/imm32/next
30074 # - floating-point inverse square root 1/sqrt(x)
30075 _Primitive-inverse-square-root-xreg-to-xreg:  # (payload primitive)
30076     0x11/imm32/alloc-id:fake:payload
30077     # var1/xreg <- reciprocal var2 => f3 0f 52/inverse-square-root var2/xm32 var1/x32
30078     0x11/imm32/alloc-id:fake
30079     _string-inverse-square-root/imm32/name
30080     0x11/imm32/alloc-id:fake
30081     Single-float-var-in-some-register/imm32/inouts
30082     0x11/imm32/alloc-id:fake
30083     Single-float-var-in-some-register/imm32/outputs
30084     0x11/imm32/alloc-id:fake
30085     _string_f3_0f_52_inverse_square_root/imm32/subx-name
30086     0/imm32/no-rm32
30087     0/imm32/no-r32
30088     0/imm32/no-imm32
30089     0/imm32/no-imm8
30090     0/imm32/no-disp32
30091     1/imm32/xm32-is-first-inout
30092     3/imm32/x32-is-first-output
30093     0x11/imm32/alloc-id:fake
30094     _Primitive-inverse-square-root-mem-to-xreg/imm32/next
30095 _Primitive-inverse-square-root-mem-to-xreg:  # (payload primitive)
30096     0x11/imm32/alloc-id:fake:payload
30097     # var1/xreg <- divide var2 => f3 0f 52/inverse-square-root var2/xm32 var1/x32
30098     0x11/imm32/alloc-id:fake
30099     _string-inverse-square-root/imm32/name
30100     0x11/imm32/alloc-id:fake
30101     Single-float-var-in-mem/imm32/inouts
30102     0x11/imm32/alloc-id:fake
30103     Single-float-var-in-some-register/imm32/outputs
30104     0x11/imm32/alloc-id:fake
30105     _string_f3_0f_52_inverse_square_root/imm32/subx-name
30106     0/imm32/no-rm32
30107     0/imm32/no-r32
30108     0/imm32/no-imm32
30109     0/imm32/no-imm8
30110     0/imm32/no-disp32
30111     1/imm32/xm32-is-first-inout
30112     3/imm32/x32-is-first-output
30113     0x11/imm32/alloc-id:fake
30114     _Primitive-compare-xreg-with-xreg/imm32/next
30115 # - floating-point compare
30116 _Primitive-compare-xreg-with-xreg:  # (payload primitive)
30117     0x11/imm32/alloc-id:fake:payload
30118     # compare var1/reg1 var2/reg2 => 0f 2f/compare var2/x32 var1/xm32
30119     0x11/imm32/alloc-id:fake
30120     _string-compare/imm32/name
30121     0x11/imm32/alloc-id:fake
30122     Two-float-args-in-regs/imm32/inouts
30123     0/imm32/no-outputs
30124     0/imm32/no-outputs
30125     0x11/imm32/alloc-id:fake
30126     _string_0f_2f_compare/imm32/subx-name
30127     0/imm32/no-rm32
30128     0/imm32/no-r32
30129     0/imm32/no-imm32
30130     0/imm32/no-imm8
30131     0/imm32/no-disp32
30132     1/imm32/xm32-is-first-inout
30133     2/imm32/x32-is-second-inout
30134     0x11/imm32/alloc-id:fake
30135     _Primitive-compare-xreg-with-mem/imm32/next
30136 _Primitive-compare-xreg-with-mem:  # (payload primitive)
30137     0x11/imm32/alloc-id:fake:payload
30138     # compare var1/xreg var2 => 0f 2f/compare var1/x32 var2/xm32
30139     0x11/imm32/alloc-id:fake
30140     _string-compare/imm32/name
30141     0x11/imm32/alloc-id:fake
30142     Two-args-float-reg-float-stack/imm32/inouts
30143     0/imm32/no-outputs
30144     0/imm32/no-outputs
30145     0x11/imm32/alloc-id:fake
30146     _string_0f_2f_compare/imm32/subx-name
30147     0/imm32/no-rm32
30148     0/imm32/no-r32
30149     0/imm32/no-imm32
30150     0/imm32/no-imm8
30151     0/imm32/no-disp32
30152     2/imm32/xm32-is-second-inout
30153     1/imm32/x32-is-first-inout
30154     0x11/imm32/alloc-id:fake
30155     _Primitive-break-if-addr</imm32/next
30156 # - branches
30157 _Primitive-break-if-addr<:  # (payload primitive)
30158     0x11/imm32/alloc-id:fake:payload
30159     0x11/imm32/alloc-id:fake
30160     _string-break-if-addr</imm32/name
30161     0/imm32/no-inouts
30162     0/imm32/no-inouts
30163     0/imm32/no-outputs
30164     0/imm32/no-outputs
30165     0x11/imm32/alloc-id:fake
30166     _string_0f_82_jump_break/imm32/subx-name
30167     0/imm32/no-rm32
30168     0/imm32/no-r32
30169     0/imm32/no-imm32
30170     0/imm32/no-imm8
30171     0/imm32/no-disp32
30172     0/imm32/no-xm32
30173     0/imm32/no-x32
30174     0x11/imm32/alloc-id:fake
30175     _Primitive-break-if-addr>=/imm32/next
30176 _Primitive-break-if-addr>=:  # (payload primitive)
30177     0x11/imm32/alloc-id:fake:payload
30178     0x11/imm32/alloc-id:fake
30179     _string-break-if-addr>=/imm32/name
30180     0/imm32/no-inouts
30181     0/imm32/no-inouts
30182     0/imm32/no-outputs
30183     0/imm32/no-outputs
30184     0x11/imm32/alloc-id:fake
30185     _string_0f_83_jump_break/imm32/subx-name
30186     0/imm32/no-rm32
30187     0/imm32/no-r32
30188     0/imm32/no-imm32
30189     0/imm32/no-imm8
30190     0/imm32/no-disp32
30191     0/imm32/no-xm32
30192     0/imm32/no-x32
30193     0x11/imm32/alloc-id:fake
30194     _Primitive-break-if-=/imm32/next
30195 _Primitive-break-if-=:  # (payload primitive)
30196     0x11/imm32/alloc-id:fake:payload
30197     0x11/imm32/alloc-id:fake
30198     _string-break-if-=/imm32/name
30199     0/imm32/no-inouts
30200     0/imm32/no-inouts
30201     0/imm32/no-outputs
30202     0/imm32/no-outputs
30203     0x11/imm32/alloc-id:fake
30204     _string_0f_84_jump_break/imm32/subx-name
30205     0/imm32/no-rm32
30206     0/imm32/no-r32
30207     0/imm32/no-imm32
30208     0/imm32/no-imm8
30209     0/imm32/no-disp32
30210     0/imm32/no-xm32
30211     0/imm32/no-x32
30212     0x11/imm32/alloc-id:fake
30213     _Primitive-break-if-!=/imm32/next
30214 _Primitive-break-if-!=:  # (payload primitive)
30215     0x11/imm32/alloc-id:fake:payload
30216     0x11/imm32/alloc-id:fake
30217     _string-break-if-!=/imm32/name
30218     0/imm32/no-inouts
30219     0/imm32/no-inouts
30220     0/imm32/no-outputs
30221     0/imm32/no-outputs
30222     0x11/imm32/alloc-id:fake
30223     _string_0f_85_jump_break/imm32/subx-name
30224     0/imm32/no-rm32
30225     0/imm32/no-r32
30226     0/imm32/no-imm32
30227     0/imm32/no-imm8
30228     0/imm32/no-disp32
30229     0/imm32/no-xm32
30230     0/imm32/no-x32
30231     0x11/imm32/alloc-id:fake
30232     _Primitive-break-if-addr<=/imm32/next
30233 _Primitive-break-if-addr<=:  # (payload primitive)
30234     0x11/imm32/alloc-id:fake:payload
30235     0x11/imm32/alloc-id:fake
30236     _string-break-if-addr<=/imm32/name
30237     0/imm32/no-inouts
30238     0/imm32/no-inouts
30239     0/imm32/no-outputs
30240     0/imm32/no-outputs
30241     0x11/imm32/alloc-id:fake
30242     _string_0f_86_jump_break/imm32/subx-name
30243     0/imm32/no-rm32
30244     0/imm32/no-r32
30245     0/imm32/no-imm32
30246     0/imm32/no-imm8
30247     0/imm32/no-disp32
30248     0/imm32/no-xm32
30249     0/imm32/no-x32
30250     0x11/imm32/alloc-id:fake
30251     _Primitive-break-if-addr>/imm32/next
30252 _Primitive-break-if-addr>:  # (payload primitive)
30253     0x11/imm32/alloc-id:fake:payload
30254     0x11/imm32/alloc-id:fake
30255     _string-break-if-addr>/imm32/name
30256     0/imm32/no-inouts
30257     0/imm32/no-inouts
30258     0/imm32/no-outputs
30259     0/imm32/no-outputs
30260     0x11/imm32/alloc-id:fake
30261     _string_0f_87_jump_break/imm32/subx-name
30262     0/imm32/no-rm32
30263     0/imm32/no-r32
30264     0/imm32/no-imm32
30265     0/imm32/no-imm8
30266     0/imm32/no-disp32
30267     0/imm32/no-xm32
30268     0/imm32/no-x32
30269     0x11/imm32/alloc-id:fake
30270     _Primitive-break-if-</imm32/next
30271 _Primitive-break-if-<:  # (payload primitive)
30272     0x11/imm32/alloc-id:fake:payload
30273     0x11/imm32/alloc-id:fake
30274     _string-break-if-</imm32/name
30275     0/imm32/no-inouts
30276     0/imm32/no-inouts
30277     0/imm32/no-outputs
30278     0/imm32/no-outputs
30279     0x11/imm32/alloc-id:fake
30280     _string_0f_8c_jump_break/imm32/subx-name
30281     0/imm32/no-rm32
30282     0/imm32/no-r32
30283     0/imm32/no-imm32
30284     0/imm32/no-imm8
30285     0/imm32/no-disp32
30286     0/imm32/no-xm32
30287     0/imm32/no-x32
30288     0x11/imm32/alloc-id:fake
30289     _Primitive-break-if->=/imm32/next
30290 _Primitive-break-if->=:  # (payload primitive)
30291     0x11/imm32/alloc-id:fake:payload
30292     0x11/imm32/alloc-id:fake
30293     _string-break-if->=/imm32/name
30294     0/imm32/no-inouts
30295     0/imm32/no-inouts
30296     0/imm32/no-outputs
30297     0/imm32/no-outputs
30298     0x11/imm32/alloc-id:fake
30299     _string_0f_8d_jump_break/imm32/subx-name
30300     0/imm32/no-rm32
30301     0/imm32/no-r32
30302     0/imm32/no-imm32
30303     0/imm32/no-imm8
30304     0/imm32/no-disp32
30305     0/imm32/no-xm32
30306     0/imm32/no-x32
30307     0x11/imm32/alloc-id:fake
30308     _Primitive-break-if-<=/imm32/next
30309 _Primitive-break-if-<=:  # (payload primitive)
30310     0x11/imm32/alloc-id:fake:payload
30311     0x11/imm32/alloc-id:fake
30312     _string-break-if-<=/imm32/name
30313     0/imm32/no-inouts
30314     0/imm32/no-inouts
30315     0/imm32/no-outputs
30316     0/imm32/no-outputs
30317     0x11/imm32/alloc-id:fake
30318     _string_0f_8e_jump_break/imm32/subx-name
30319     0/imm32/no-rm32
30320     0/imm32/no-r32
30321     0/imm32/no-imm32
30322     0/imm32/no-imm8
30323     0/imm32/no-disp32
30324     0/imm32/no-xm32
30325     0/imm32/no-x32
30326     0x11/imm32/alloc-id:fake
30327     _Primitive-break-if->/imm32/next
30328 _Primitive-break-if->:  # (payload primitive)
30329     0x11/imm32/alloc-id:fake:payload
30330     0x11/imm32/alloc-id:fake
30331     _string-break-if->/imm32/name
30332     0/imm32/no-inouts
30333     0/imm32/no-inouts
30334     0/imm32/no-outputs
30335     0/imm32/no-outputs
30336     0x11/imm32/alloc-id:fake
30337     _string_0f_8f_jump_break/imm32/subx-name
30338     0/imm32/no-rm32
30339     0/imm32/no-r32
30340     0/imm32/no-imm32
30341     0/imm32/no-imm8
30342     0/imm32/no-disp32
30343     0/imm32/no-xm32
30344     0/imm32/no-x32
30345     0x11/imm32/alloc-id:fake
30346     _Primitive-break/imm32/next
30347 _Primitive-break:  # (payload primitive)
30348     0x11/imm32/alloc-id:fake:payload
30349     0x11/imm32/alloc-id:fake
30350     _string-break/imm32/name
30351     0/imm32/no-inouts
30352     0/imm32/no-inouts
30353     0/imm32/no-outputs
30354     0/imm32/no-outputs
30355     0x11/imm32/alloc-id:fake
30356     _string_e9_jump_break/imm32/subx-name
30357     0/imm32/no-rm32
30358     0/imm32/no-r32
30359     0/imm32/no-imm32
30360     0/imm32/no-imm8
30361     0/imm32/no-disp32
30362     0/imm32/no-xm32
30363     0/imm32/no-x32
30364     0x11/imm32/alloc-id:fake
30365     _Primitive-loop-if-addr</imm32/next
30366 _Primitive-loop-if-addr<:  # (payload primitive)
30367     0x11/imm32/alloc-id:fake:payload
30368     0x11/imm32/alloc-id:fake
30369     _string-loop-if-addr</imm32/name
30370     0/imm32/no-inouts
30371     0/imm32/no-inouts
30372     0/imm32/no-outputs
30373     0/imm32/no-outputs
30374     0x11/imm32/alloc-id:fake
30375     _string_0f_82_jump_loop/imm32/subx-name
30376     0/imm32/no-rm32
30377     0/imm32/no-r32
30378     0/imm32/no-imm32
30379     0/imm32/no-imm8
30380     0/imm32/no-disp32
30381     0/imm32/no-xm32
30382     0/imm32/no-x32
30383     0x11/imm32/alloc-id:fake
30384     _Primitive-loop-if-addr>=/imm32/next
30385 _Primitive-loop-if-addr>=:  # (payload primitive)
30386     0x11/imm32/alloc-id:fake:payload
30387     0x11/imm32/alloc-id:fake
30388     _string-loop-if-addr>=/imm32/name
30389     0/imm32/no-inouts
30390     0/imm32/no-inouts
30391     0/imm32/no-outputs
30392     0/imm32/no-outputs
30393     0x11/imm32/alloc-id:fake
30394     _string_0f_83_jump_loop/imm32/subx-name
30395     0/imm32/no-rm32
30396     0/imm32/no-r32
30397     0/imm32/no-imm32
30398     0/imm32/no-imm8
30399     0/imm32/no-disp32
30400     0/imm32/no-xm32
30401     0/imm32/no-x32
30402     0x11/imm32/alloc-id:fake
30403     _Primitive-loop-if-=/imm32/next
30404 _Primitive-loop-if-=:  # (payload primitive)
30405     0x11/imm32/alloc-id:fake:payload
30406     0x11/imm32/alloc-id:fake
30407     _string-loop-if-=/imm32/name
30408     0/imm32/no-inouts
30409     0/imm32/no-inouts
30410     0/imm32/no-outputs
30411     0/imm32/no-outputs
30412     0x11/imm32/alloc-id:fake
30413     _string_0f_84_jump_loop/imm32/subx-name
30414     0/imm32/no-rm32
30415     0/imm32/no-r32
30416     0/imm32/no-imm32
30417     0/imm32/no-imm8
30418     0/imm32/no-disp32
30419     0/imm32/no-xm32
30420     0/imm32/no-x32
30421     0x11/imm32/alloc-id:fake
30422     _Primitive-loop-if-!=/imm32/next
30423 _Primitive-loop-if-!=:  # (payload primitive)
30424     0x11/imm32/alloc-id:fake:payload
30425     0x11/imm32/alloc-id:fake
30426     _string-loop-if-!=/imm32/name
30427     0/imm32/no-inouts
30428     0/imm32/no-inouts
30429     0/imm32/no-outputs
30430     0/imm32/no-outputs
30431     0x11/imm32/alloc-id:fake
30432     _string_0f_85_jump_loop/imm32/subx-name
30433     0/imm32/no-rm32
30434     0/imm32/no-r32
30435     0/imm32/no-imm32
30436     0/imm32/no-imm8
30437     0/imm32/no-disp32
30438     0/imm32/no-xm32
30439     0/imm32/no-x32
30440     0x11/imm32/alloc-id:fake
30441     _Primitive-loop-if-addr<=/imm32/next
30442 _Primitive-loop-if-addr<=:  # (payload primitive)
30443     0x11/imm32/alloc-id:fake:payload
30444     0x11/imm32/alloc-id:fake
30445     _string-loop-if-addr<=/imm32/name
30446     0/imm32/no-inouts
30447     0/imm32/no-inouts
30448     0/imm32/no-outputs
30449     0/imm32/no-outputs
30450     0x11/imm32/alloc-id:fake
30451     _string_0f_86_jump_loop/imm32/subx-name
30452     0/imm32/no-rm32
30453     0/imm32/no-r32
30454     0/imm32/no-imm32
30455     0/imm32/no-imm8
30456     0/imm32/no-disp32
30457     0/imm32/no-xm32
30458     0/imm32/no-x32
30459     0x11/imm32/alloc-id:fake
30460     _Primitive-loop-if-addr>/imm32/next
30461 _Primitive-loop-if-addr>:  # (payload primitive)
30462     0x11/imm32/alloc-id:fake:payload
30463     0x11/imm32/alloc-id:fake
30464     _string-loop-if-addr>/imm32/name
30465     0/imm32/no-inouts
30466     0/imm32/no-inouts
30467     0/imm32/no-outputs
30468     0/imm32/no-outputs
30469     0x11/imm32/alloc-id:fake
30470     _string_0f_87_jump_loop/imm32/subx-name
30471     0/imm32/no-rm32
30472     0/imm32/no-r32
30473     0/imm32/no-imm32
30474     0/imm32/no-imm8
30475     0/imm32/no-disp32
30476     0/imm32/no-xm32
30477     0/imm32/no-x32
30478     0x11/imm32/alloc-id:fake
30479     _Primitive-loop-if-</imm32/next
30480 _Primitive-loop-if-<:  # (payload primitive)
30481     0x11/imm32/alloc-id:fake:payload
30482     0x11/imm32/alloc-id:fake
30483     _string-loop-if-</imm32/name
30484     0/imm32/no-inouts
30485     0/imm32/no-inouts
30486     0/imm32/no-outputs
30487     0/imm32/no-outputs
30488     0x11/imm32/alloc-id:fake
30489     _string_0f_8c_jump_loop/imm32/subx-name
30490     0/imm32/no-rm32
30491     0/imm32/no-r32
30492     0/imm32/no-imm32
30493     0/imm32/no-imm8
30494     0/imm32/no-disp32
30495     0/imm32/no-xm32
30496     0/imm32/no-x32
30497     0x11/imm32/alloc-id:fake
30498     _Primitive-loop-if->=/imm32/next
30499 _Primitive-loop-if->=:  # (payload primitive)
30500     0x11/imm32/alloc-id:fake:payload
30501     0x11/imm32/alloc-id:fake
30502     _string-loop-if->=/imm32/name
30503     0/imm32/no-inouts
30504     0/imm32/no-inouts
30505     0/imm32/no-outputs
30506     0/imm32/no-outputs
30507     0x11/imm32/alloc-id:fake
30508     _string_0f_8d_jump_loop/imm32/subx-name
30509     0/imm32/no-rm32
30510     0/imm32/no-r32
30511     0/imm32/no-imm32
30512     0/imm32/no-imm8
30513     0/imm32/no-disp32
30514     0/imm32/no-xm32
30515     0/imm32/no-x32
30516     0x11/imm32/alloc-id:fake
30517     _Primitive-loop-if-<=/imm32/next
30518 _Primitive-loop-if-<=:  # (payload primitive)
30519     0x11/imm32/alloc-id:fake:payload
30520     0x11/imm32/alloc-id:fake
30521     _string-loop-if-<=/imm32/name
30522     0/imm32/no-inouts
30523     0/imm32/no-inouts
30524     0/imm32/no-outputs
30525     0/imm32/no-outputs
30526     0x11/imm32/alloc-id:fake
30527     _string_0f_8e_jump_loop/imm32/subx-name
30528     0/imm32/no-rm32
30529     0/imm32/no-r32
30530     0/imm32/no-imm32
30531     0/imm32/no-imm8
30532     0/imm32/no-disp32
30533     0/imm32/no-xm32
30534     0/imm32/no-x32
30535     0x11/imm32/alloc-id:fake
30536     _Primitive-loop-if->/imm32/next
30537 _Primitive-loop-if->:  # (payload primitive)
30538     0x11/imm32/alloc-id:fake:payload
30539     0x11/imm32/alloc-id:fake
30540     _string-loop-if->/imm32/name
30541     0/imm32/no-inouts
30542     0/imm32/no-inouts
30543     0/imm32/no-outputs
30544     0/imm32/no-outputs
30545     0x11/imm32/alloc-id:fake
30546     _string_0f_8f_jump_loop/imm32/subx-name
30547     0/imm32/no-rm32
30548     0/imm32/no-r32
30549     0/imm32/no-imm32
30550     0/imm32/no-imm8
30551     0/imm32/no-disp32
30552     0/imm32/no-xm32
30553     0/imm32/no-x32
30554     0x11/imm32/alloc-id:fake
30555     _Primitive-loop/imm32/next  # we probably don't need an unconditional break
30556 _Primitive-loop:  # (payload primitive)
30557     0x11/imm32/alloc-id:fake:payload
30558     0x11/imm32/alloc-id:fake
30559     _string-loop/imm32/name
30560     0/imm32/no-inouts
30561     0/imm32/no-inouts
30562     0/imm32/no-outputs
30563     0/imm32/no-outputs
30564     0x11/imm32/alloc-id:fake
30565     _string_e9_jump_loop/imm32/subx-name
30566     0/imm32/no-rm32
30567     0/imm32/no-r32
30568     0/imm32/no-imm32
30569     0/imm32/no-imm8
30570     0/imm32/no-disp32
30571     0/imm32/no-xm32
30572     0/imm32/no-x32
30573     0x11/imm32/alloc-id:fake
30574     _Primitive-break-if-addr<-named/imm32/next
30575 # - branches to named blocks
30576 _Primitive-break-if-addr<-named:  # (payload primitive)
30577     0x11/imm32/alloc-id:fake:payload
30578     0x11/imm32/alloc-id:fake
30579     _string-break-if-addr</imm32/name
30580     0x11/imm32/alloc-id:fake
30581     Single-lit-var/imm32/inouts
30582     0/imm32/no-outputs
30583     0/imm32/no-outputs
30584     0x11/imm32/alloc-id:fake
30585     _string_0f_82_jump_label/imm32/subx-name
30586     0/imm32/no-rm32
30587     0/imm32/no-r32
30588     0/imm32/no-imm32
30589     0/imm32/no-imm8
30590     1/imm32/disp32-is-first-inout
30591     0/imm32/no-xm32
30592     0/imm32/no-x32
30593     0x11/imm32/alloc-id:fake
30594     _Primitive-break-if-addr>=-named/imm32/next
30595 _Primitive-break-if-addr>=-named:  # (payload primitive)
30596     0x11/imm32/alloc-id:fake:payload
30597     0x11/imm32/alloc-id:fake
30598     _string-break-if-addr>=/imm32/name
30599     0x11/imm32/alloc-id:fake
30600     Single-lit-var/imm32/inouts
30601     0/imm32/no-outputs
30602     0/imm32/no-outputs
30603     0x11/imm32/alloc-id:fake
30604     _string_0f_83_jump_label/imm32/subx-name
30605     0/imm32/no-rm32
30606     0/imm32/no-r32
30607     0/imm32/no-imm32
30608     0/imm32/no-imm8
30609     1/imm32/disp32-is-first-inout
30610     0/imm32/no-xm32
30611     0/imm32/no-x32
30612     0x11/imm32/alloc-id:fake
30613     _Primitive-break-if-=-named/imm32/next
30614 _Primitive-break-if-=-named:  # (payload primitive)
30615     0x11/imm32/alloc-id:fake:payload
30616     0x11/imm32/alloc-id:fake
30617     _string-break-if-=/imm32/name
30618     0x11/imm32/alloc-id:fake
30619     Single-lit-var/imm32/inouts
30620     0/imm32/no-outputs
30621     0/imm32/no-outputs
30622     0x11/imm32/alloc-id:fake
30623     _string_0f_84_jump_label/imm32/subx-name
30624     0/imm32/no-rm32
30625     0/imm32/no-r32
30626     0/imm32/no-imm32
30627     0/imm32/no-imm8
30628     1/imm32/disp32-is-first-inout
30629     0/imm32/no-xm32
30630     0/imm32/no-x32
30631     0x11/imm32/alloc-id:fake
30632     _Primitive-break-if-!=-named/imm32/next
30633 _Primitive-break-if-!=-named:  # (payload primitive)
30634     0x11/imm32/alloc-id:fake:payload
30635     0x11/imm32/alloc-id:fake
30636     _string-break-if-!=/imm32/name
30637     0x11/imm32/alloc-id:fake
30638     Single-lit-var/imm32/inouts
30639     0/imm32/no-outputs
30640     0/imm32/no-outputs
30641     0x11/imm32/alloc-id:fake
30642     _string_0f_85_jump_label/imm32/subx-name
30643     0/imm32/no-rm32
30644     0/imm32/no-r32
30645     0/imm32/no-imm32
30646     0/imm32/no-imm8
30647     1/imm32/disp32-is-first-inout
30648     0/imm32/no-xm32
30649     0/imm32/no-x32
30650     0x11/imm32/alloc-id:fake
30651     _Primitive-break-if-addr<=-named/imm32/next
30652 _Primitive-break-if-addr<=-named:  # (payload primitive)
30653     0x11/imm32/alloc-id:fake:payload
30654     0x11/imm32/alloc-id:fake
30655     _string-break-if-addr<=/imm32/name
30656     0x11/imm32/alloc-id:fake
30657     Single-lit-var/imm32/inouts
30658     0/imm32/no-outputs
30659     0/imm32/no-outputs
30660     0x11/imm32/alloc-id:fake
30661     _string_0f_86_jump_label/imm32/subx-name
30662     0/imm32/no-rm32
30663     0/imm32/no-r32
30664     0/imm32/no-imm32
30665     0/imm32/no-imm8
30666     1/imm32/disp32-is-first-inout
30667     0/imm32/no-xm32
30668     0/imm32/no-x32
30669     0x11/imm32/alloc-id:fake
30670     _Primitive-break-if-addr>-named/imm32/next
30671 _Primitive-break-if-addr>-named:  # (payload primitive)
30672     0x11/imm32/alloc-id:fake:payload
30673     0x11/imm32/alloc-id:fake
30674     _string-break-if-addr>/imm32/name
30675     0x11/imm32/alloc-id:fake
30676     Single-lit-var/imm32/inouts
30677     0/imm32/no-outputs
30678     0/imm32/no-outputs
30679     0x11/imm32/alloc-id:fake
30680     _string_0f_87_jump_label/imm32/subx-name
30681     0/imm32/no-rm32
30682     0/imm32/no-r32
30683     0/imm32/no-imm32
30684     0/imm32/no-imm8
30685     1/imm32/disp32-is-first-inout
30686     0/imm32/no-xm32
30687     0/imm32/no-x32
30688     0x11/imm32/alloc-id:fake
30689     _Primitive-break-if-<-named/imm32/next
30690 _Primitive-break-if-<-named:  # (payload primitive)
30691     0x11/imm32/alloc-id:fake:payload
30692     0x11/imm32/alloc-id:fake
30693     _string-break-if-</imm32/name
30694     0x11/imm32/alloc-id:fake
30695     Single-lit-var/imm32/inouts
30696     0/imm32/no-outputs
30697     0/imm32/no-outputs
30698     0x11/imm32/alloc-id:fake
30699     _string_0f_8c_jump_label/imm32/subx-name
30700     0/imm32/no-rm32
30701     0/imm32/no-r32
30702     0/imm32/no-imm32
30703     0/imm32/no-imm8
30704     1/imm32/disp32-is-first-inout
30705     0/imm32/no-xm32
30706     0/imm32/no-x32
30707     0x11/imm32/alloc-id:fake
30708     _Primitive-break-if->=-named/imm32/next
30709 _Primitive-break-if->=-named:  # (payload primitive)
30710     0x11/imm32/alloc-id:fake:payload
30711     0x11/imm32/alloc-id:fake
30712     _string-break-if->=/imm32/name
30713     0x11/imm32/alloc-id:fake
30714     Single-lit-var/imm32/inouts
30715     0/imm32/no-outputs
30716     0/imm32/no-outputs
30717     0x11/imm32/alloc-id:fake
30718     _string_0f_8d_jump_label/imm32/subx-name
30719     0/imm32/no-rm32
30720     0/imm32/no-r32
30721     0/imm32/no-imm32
30722     0/imm32/no-imm8
30723     1/imm32/disp32-is-first-inout
30724     0/imm32/no-xm32
30725     0/imm32/no-x32
30726     0x11/imm32/alloc-id:fake
30727     _Primitive-break-if-<=-named/imm32/next
30728 _Primitive-break-if-<=-named:  # (payload primitive)
30729     0x11/imm32/alloc-id:fake:payload
30730     0x11/imm32/alloc-id:fake
30731     _string-break-if-<=/imm32/name
30732     0x11/imm32/alloc-id:fake
30733     Single-lit-var/imm32/inouts
30734     0/imm32/no-outputs
30735     0/imm32/no-outputs
30736     0x11/imm32/alloc-id:fake
30737     _string_0f_8e_jump_label/imm32/subx-name
30738     0/imm32/no-rm32
30739     0/imm32/no-r32
30740     0/imm32/no-imm32
30741     0/imm32/no-imm8
30742     1/imm32/disp32-is-first-inout
30743     0/imm32/no-xm32
30744     0/imm32/no-x32
30745     0x11/imm32/alloc-id:fake
30746     _Primitive-break-if->-named/imm32/next
30747 _Primitive-break-if->-named:  # (payload primitive)
30748     0x11/imm32/alloc-id:fake:payload
30749     0x11/imm32/alloc-id:fake
30750     _string-break-if->/imm32/name
30751     0x11/imm32/alloc-id:fake
30752     Single-lit-var/imm32/inouts
30753     0/imm32/no-outputs
30754     0/imm32/no-outputs
30755     0x11/imm32/alloc-id:fake
30756     _string_0f_8f_jump_label/imm32/subx-name
30757     0/imm32/no-rm32
30758     0/imm32/no-r32
30759     0/imm32/no-imm32
30760     0/imm32/no-imm8
30761     1/imm32/disp32-is-first-inout
30762     0/imm32/no-xm32
30763     0/imm32/no-x32
30764     0x11/imm32/alloc-id:fake
30765     _Primitive-break-named/imm32/next
30766 _Primitive-break-named:  # (payload primitive)
30767     0x11/imm32/alloc-id:fake:payload
30768     0x11/imm32/alloc-id:fake
30769     _string-break/imm32/name
30770     0x11/imm32/alloc-id:fake
30771     Single-lit-var/imm32/inouts
30772     0/imm32/no-outputs
30773     0/imm32/no-outputs
30774     0x11/imm32/alloc-id:fake
30775     _string_e9_jump_label/imm32/subx-name
30776     0/imm32/no-rm32
30777     0/imm32/no-r32
30778     0/imm32/no-imm32
30779     0/imm32/no-imm8
30780     1/imm32/disp32-is-first-inout
30781     0/imm32/no-xm32
30782     0/imm32/no-x32
30783     0x11/imm32/alloc-id:fake
30784     _Primitive-loop-if-addr<-named/imm32/next
30785 _Primitive-loop-if-addr<-named:  # (payload primitive)
30786     0x11/imm32/alloc-id:fake:payload
30787     0x11/imm32/alloc-id:fake
30788     _string-loop-if-addr</imm32/name
30789     0x11/imm32/alloc-id:fake
30790     Single-lit-var/imm32/inouts
30791     0/imm32/no-outputs
30792     0/imm32/no-outputs
30793     0x11/imm32/alloc-id:fake
30794     _string_0f_82_jump_label/imm32/subx-name
30795     0/imm32/no-rm32
30796     0/imm32/no-r32
30797     0/imm32/no-imm32
30798     0/imm32/no-imm8
30799     1/imm32/disp32-is-first-inout
30800     0/imm32/no-xm32
30801     0/imm32/no-x32
30802     0x11/imm32/alloc-id:fake
30803     _Primitive-loop-if-addr>=-named/imm32/next
30804 _Primitive-loop-if-addr>=-named:  # (payload primitive)
30805     0x11/imm32/alloc-id:fake:payload
30806     0x11/imm32/alloc-id:fake
30807     _string-loop-if-addr>=/imm32/name
30808     0x11/imm32/alloc-id:fake
30809     Single-lit-var/imm32/inouts
30810     0/imm32/no-outputs
30811     0/imm32/no-outputs
30812     0x11/imm32/alloc-id:fake
30813     _string_0f_83_jump_label/imm32/subx-name
30814     0/imm32/no-rm32
30815     0/imm32/no-r32
30816     0/imm32/no-imm32
30817     0/imm32/no-imm8
30818     1/imm32/disp32-is-first-inout
30819     0/imm32/no-xm32
30820     0/imm32/no-x32
30821     0x11/imm32/alloc-id:fake
30822     _Primitive-loop-if-=-named/imm32/next
30823 _Primitive-loop-if-=-named:  # (payload primitive)
30824     0x11/imm32/alloc-id:fake:payload
30825     0x11/imm32/alloc-id:fake
30826     _string-loop-if-=/imm32/name
30827     0x11/imm32/alloc-id:fake
30828     Single-lit-var/imm32/inouts
30829     0/imm32/no-outputs
30830     0/imm32/no-outputs
30831     0x11/imm32/alloc-id:fake
30832     _string_0f_84_jump_label/imm32/subx-name
30833     0/imm32/no-rm32
30834     0/imm32/no-r32
30835     0/imm32/no-imm32
30836     0/imm32/no-imm8
30837     1/imm32/disp32-is-first-inout
30838     0/imm32/no-xm32
30839     0/imm32/no-x32
30840     0x11/imm32/alloc-id:fake
30841     _Primitive-loop-if-!=-named/imm32/next
30842 _Primitive-loop-if-!=-named:  # (payload primitive)
30843     0x11/imm32/alloc-id:fake:payload
30844     0x11/imm32/alloc-id:fake
30845     _string-loop-if-!=/imm32/name
30846     0x11/imm32/alloc-id:fake
30847     Single-lit-var/imm32/inouts
30848     0/imm32/no-outputs
30849     0/imm32/no-outputs
30850     0x11/imm32/alloc-id:fake
30851     _string_0f_85_jump_label/imm32/subx-name
30852     0/imm32/no-rm32
30853     0/imm32/no-r32
30854     0/imm32/no-imm32
30855     0/imm32/no-imm8
30856     1/imm32/disp32-is-first-inout
30857     0/imm32/no-xm32
30858     0/imm32/no-x32
30859     0x11/imm32/alloc-id:fake
30860     _Primitive-loop-if-addr<=-named/imm32/next
30861 _Primitive-loop-if-addr<=-named:  # (payload primitive)
30862     0x11/imm32/alloc-id:fake:payload
30863     0x11/imm32/alloc-id:fake
30864     _string-loop-if-addr<=/imm32/name
30865     0x11/imm32/alloc-id:fake
30866     Single-lit-var/imm32/inouts
30867     0/imm32/no-outputs
30868     0/imm32/no-outputs
30869     0x11/imm32/alloc-id:fake
30870     _string_0f_86_jump_label/imm32/subx-name
30871     0/imm32/no-rm32
30872     0/imm32/no-r32
30873     0/imm32/no-imm32
30874     0/imm32/no-imm8
30875     1/imm32/disp32-is-first-inout
30876     0/imm32/no-xm32
30877     0/imm32/no-x32
30878     0x11/imm32/alloc-id:fake
30879     _Primitive-loop-if-addr>-named/imm32/next
30880 _Primitive-loop-if-addr>-named:  # (payload primitive)
30881     0x11/imm32/alloc-id:fake:payload
30882     0x11/imm32/alloc-id:fake
30883     _string-loop-if-addr>/imm32/name
30884     0x11/imm32/alloc-id:fake
30885     Single-lit-var/imm32/inouts
30886     0/imm32/no-outputs
30887     0/imm32/no-outputs
30888     0x11/imm32/alloc-id:fake
30889     _string_0f_87_jump_label/imm32/subx-name
30890     0/imm32/no-rm32
30891     0/imm32/no-r32
30892     0/imm32/no-imm32
30893     0/imm32/no-imm8
30894     1/imm32/disp32-is-first-inout
30895     0/imm32/no-xm32
30896     0/imm32/no-x32
30897     0x11/imm32/alloc-id:fake
30898     _Primitive-loop-if-<-named/imm32/next
30899 _Primitive-loop-if-<-named:  # (payload primitive)
30900     0x11/imm32/alloc-id:fake:payload
30901     0x11/imm32/alloc-id:fake
30902     _string-loop-if-</imm32/name
30903     0x11/imm32/alloc-id:fake
30904     Single-lit-var/imm32/inouts
30905     0/imm32/no-outputs
30906     0/imm32/no-outputs
30907     0x11/imm32/alloc-id:fake
30908     _string_0f_8c_jump_label/imm32/subx-name
30909     0/imm32/no-rm32
30910     0/imm32/no-r32
30911     0/imm32/no-imm32
30912     0/imm32/no-imm8
30913     1/imm32/disp32-is-first-inout
30914     0/imm32/no-xm32
30915     0/imm32/no-x32
30916     0x11/imm32/alloc-id:fake
30917     _Primitive-loop-if->=-named/imm32/next
30918 _Primitive-loop-if->=-named:  # (payload primitive)
30919     0x11/imm32/alloc-id:fake:payload
30920     0x11/imm32/alloc-id:fake
30921     _string-loop-if->=/imm32/name
30922     0x11/imm32/alloc-id:fake
30923     Single-lit-var/imm32/inouts
30924     0/imm32/no-outputs
30925     0/imm32/no-outputs
30926     0x11/imm32/alloc-id:fake
30927     _string_0f_8d_jump_label/imm32/subx-name
30928     0/imm32/no-rm32
30929     0/imm32/no-r32
30930     0/imm32/no-imm32
30931     0/imm32/no-imm8
30932     1/imm32/disp32-is-first-inout
30933     0/imm32/no-xm32
30934     0/imm32/no-x32
30935     0x11/imm32/alloc-id:fake
30936     _Primitive-loop-if-<=-named/imm32/next
30937 _Primitive-loop-if-<=-named:  # (payload primitive)
30938     0x11/imm32/alloc-id:fake:payload
30939     0x11/imm32/alloc-id:fake
30940     _string-loop-if-<=/imm32/name
30941     0x11/imm32/alloc-id:fake
30942     Single-lit-var/imm32/inouts
30943     0/imm32/no-outputs
30944     0/imm32/no-outputs
30945     0x11/imm32/alloc-id:fake
30946     _string_0f_8e_jump_label/imm32/subx-name
30947     0/imm32/no-rm32
30948     0/imm32/no-r32
30949     0/imm32/no-imm32
30950     0/imm32/no-imm8
30951     1/imm32/disp32-is-first-inout
30952     0/imm32/no-xm32
30953     0/imm32/no-x32
30954     0x11/imm32/alloc-id:fake
30955     _Primitive-loop-if->-named/imm32/next
30956 _Primitive-loop-if->-named:  # (payload primitive)
30957     0x11/imm32/alloc-id:fake:payload
30958     0x11/imm32/alloc-id:fake
30959     _string-loop-if->/imm32/name
30960     0x11/imm32/alloc-id:fake
30961     Single-lit-var/imm32/inouts
30962     0/imm32/no-outputs
30963     0/imm32/no-outputs
30964     0x11/imm32/alloc-id:fake
30965     _string_0f_8f_jump_label/imm32/subx-name
30966     0/imm32/no-rm32
30967     0/imm32/no-r32
30968     0/imm32/no-imm32
30969     0/imm32/no-imm8
30970     1/imm32/disp32-is-first-inout
30971     0/imm32/no-xm32
30972     0/imm32/no-x32
30973     0x11/imm32/alloc-id:fake
30974     _Primitive-loop-named/imm32/next  # we probably don't need an unconditional break
30975 _Primitive-loop-named:  # (payload primitive)
30976     0x11/imm32/alloc-id:fake:payload
30977     0x11/imm32/alloc-id:fake
30978     _string-loop/imm32/name
30979     0x11/imm32/alloc-id:fake
30980     Single-lit-var/imm32/inouts
30981     0/imm32/no-outputs
30982     0/imm32/no-outputs
30983     0x11/imm32/alloc-id:fake
30984     _string_e9_jump_label/imm32/subx-name
30985     0/imm32/no-rm32
30986     0/imm32/no-r32
30987     0/imm32/no-imm32
30988     0/imm32/no-imm8
30989     1/imm32/disp32-is-first-inout
30990     0/imm32/no-xm32
30991     0/imm32/no-x32
30992     0x11/imm32/alloc-id:fake
30993     _Primitive-break-if-float</imm32/next
30994 # - branches based on floating-point comparisons
30995 _Primitive-break-if-float<:  # (payload primitive)
30996     0x11/imm32/alloc-id:fake:payload
30997     0x11/imm32/alloc-id:fake
30998     _string-break-if-float</imm32/name
30999     0/imm32/no-inouts
31000     0/imm32/no-inouts
31001     0/imm32/no-outputs
31002     0/imm32/no-outputs
31003     0x11/imm32/alloc-id:fake
31004     _string_0f_82_jump_break/imm32/subx-name
31005     0/imm32/no-rm32
31006     0/imm32/no-r32
31007     0/imm32/no-imm32
31008     0/imm32/no-imm8
31009     0/imm32/no-disp32
31010     0/imm32/no-xm32
31011     0/imm32/no-x32
31012     0x11/imm32/alloc-id:fake
31013     _Primitive-break-if-float>=/imm32/next
31014 _Primitive-break-if-float>=:  # (payload primitive)
31015     0x11/imm32/alloc-id:fake:payload
31016     0x11/imm32/alloc-id:fake
31017     _string-break-if-float>=/imm32/name
31018     0/imm32/no-inouts
31019     0/imm32/no-inouts
31020     0/imm32/no-outputs
31021     0/imm32/no-outputs
31022     0x11/imm32/alloc-id:fake
31023     _string_0f_83_jump_break/imm32/subx-name
31024     0/imm32/no-rm32
31025     0/imm32/no-r32
31026     0/imm32/no-imm32
31027     0/imm32/no-imm8
31028     0/imm32/no-disp32
31029     0/imm32/no-xm32
31030     0/imm32/no-x32
31031     0x11/imm32/alloc-id:fake
31032     _Primitive-break-if-float<=/imm32/next
31033 _Primitive-break-if-float<=:  # (payload primitive)
31034     0x11/imm32/alloc-id:fake:payload
31035     0x11/imm32/alloc-id:fake
31036     _string-break-if-float<=/imm32/name
31037     0/imm32/no-inouts
31038     0/imm32/no-inouts
31039     0/imm32/no-outputs
31040     0/imm32/no-outputs
31041     0x11/imm32/alloc-id:fake
31042     _string_0f_86_jump_break/imm32/subx-name
31043     0/imm32/no-rm32
31044     0/imm32/no-r32
31045     0/imm32/no-imm32
31046     0/imm32/no-imm8
31047     0/imm32/no-disp32
31048     0/imm32/no-xm32
31049     0/imm32/no-x32
31050     0x11/imm32/alloc-id:fake
31051     _Primitive-break-if-float>/imm32/next
31052 _Primitive-break-if-float>:  # (payload primitive)
31053     0x11/imm32/alloc-id:fake:payload
31054     0x11/imm32/alloc-id:fake
31055     _string-break-if-float>/imm32/name
31056     0/imm32/no-inouts
31057     0/imm32/no-inouts
31058     0/imm32/no-outputs
31059     0/imm32/no-outputs
31060     0x11/imm32/alloc-id:fake
31061     _string_0f_87_jump_break/imm32/subx-name
31062     0/imm32/no-rm32
31063     0/imm32/no-r32
31064     0/imm32/no-imm32
31065     0/imm32/no-imm8
31066     0/imm32/no-disp32
31067     0/imm32/no-xm32
31068     0/imm32/no-x32
31069     0x11/imm32/alloc-id:fake
31070     _Primitive-loop-if-float</imm32/next
31071 _Primitive-loop-if-float<:  # (payload primitive)
31072     0x11/imm32/alloc-id:fake:payload
31073     0x11/imm32/alloc-id:fake
31074     _string-loop-if-float</imm32/name
31075     0/imm32/no-inouts
31076     0/imm32/no-inouts
31077     0/imm32/no-outputs
31078     0/imm32/no-outputs
31079     0x11/imm32/alloc-id:fake
31080     _string_0f_82_jump_loop/imm32/subx-name
31081     0/imm32/no-rm32
31082     0/imm32/no-r32
31083     0/imm32/no-imm32
31084     0/imm32/no-imm8
31085     0/imm32/no-disp32
31086     0/imm32/no-xm32
31087     0/imm32/no-x32
31088     0x11/imm32/alloc-id:fake
31089     _Primitive-loop-if-float>=/imm32/next
31090 _Primitive-loop-if-float>=:  # (payload primitive)
31091     0x11/imm32/alloc-id:fake:payload
31092     0x11/imm32/alloc-id:fake
31093     _string-loop-if-float>=/imm32/name
31094     0/imm32/no-inouts
31095     0/imm32/no-inouts
31096     0/imm32/no-outputs
31097     0/imm32/no-outputs
31098     0x11/imm32/alloc-id:fake
31099     _string_0f_83_jump_loop/imm32/subx-name
31100     0/imm32/no-rm32
31101     0/imm32/no-r32
31102     0/imm32/no-imm32
31103     0/imm32/no-imm8
31104     0/imm32/no-disp32
31105     0/imm32/no-xm32
31106     0/imm32/no-x32
31107     0x11/imm32/alloc-id:fake
31108     _Primitive-loop-if-float<=/imm32/next
31109 _Primitive-loop-if-float<=:  # (payload primitive)
31110     0x11/imm32/alloc-id:fake:payload
31111     0x11/imm32/alloc-id:fake
31112     _string-loop-if-float<=/imm32/name
31113     0/imm32/no-inouts
31114     0/imm32/no-inouts
31115     0/imm32/no-outputs
31116     0/imm32/no-outputs
31117     0x11/imm32/alloc-id:fake
31118     _string_0f_86_jump_loop/imm32/subx-name
31119     0/imm32/no-rm32
31120     0/imm32/no-r32
31121     0/imm32/no-imm32
31122     0/imm32/no-imm8
31123     0/imm32/no-disp32
31124     0/imm32/no-xm32
31125     0/imm32/no-x32
31126     0x11/imm32/alloc-id:fake
31127     _Primitive-loop-if-float>/imm32/next
31128 _Primitive-loop-if-float>:  # (payload primitive)
31129     0x11/imm32/alloc-id:fake:payload
31130     0x11/imm32/alloc-id:fake
31131     _string-loop-if-float>/imm32/name
31132     0/imm32/no-inouts
31133     0/imm32/no-inouts
31134     0/imm32/no-outputs
31135     0/imm32/no-outputs
31136     0x11/imm32/alloc-id:fake
31137     _string_0f_87_jump_loop/imm32/subx-name
31138     0/imm32/no-rm32
31139     0/imm32/no-r32
31140     0/imm32/no-imm32
31141     0/imm32/no-imm8
31142     0/imm32/no-disp32
31143     0/imm32/no-xm32
31144     0/imm32/no-x32
31145     0x11/imm32/alloc-id:fake
31146     _Primitive-break-if-float<-named/imm32/next
31147 _Primitive-break-if-float<-named:  # (payload primitive)
31148     0x11/imm32/alloc-id:fake:payload
31149     0x11/imm32/alloc-id:fake
31150     _string-break-if-float</imm32/name
31151     0x11/imm32/alloc-id:fake
31152     Single-lit-var/imm32/inouts
31153     0/imm32/no-outputs
31154     0/imm32/no-outputs
31155     0x11/imm32/alloc-id:fake
31156     _string_0f_82_jump_label/imm32/subx-name
31157     0/imm32/no-rm32
31158     0/imm32/no-r32
31159     0/imm32/no-imm32
31160     0/imm32/no-imm8
31161     1/imm32/disp32-is-first-inout
31162     0/imm32/no-xm32
31163     0/imm32/no-x32
31164     0x11/imm32/alloc-id:fake
31165     _Primitive-break-if-float>=-named/imm32/next
31166 _Primitive-break-if-float>=-named:  # (payload primitive)
31167     0x11/imm32/alloc-id:fake:payload
31168     0x11/imm32/alloc-id:fake
31169     _string-break-if-float>=/imm32/name
31170     0x11/imm32/alloc-id:fake
31171     Single-lit-var/imm32/inouts
31172     0/imm32/no-outputs
31173     0/imm32/no-outputs
31174     0x11/imm32/alloc-id:fake
31175     _string_0f_83_jump_label/imm32/subx-name
31176     0/imm32/no-rm32
31177     0/imm32/no-r32
31178     0/imm32/no-imm32
31179     0/imm32/no-imm8
31180     1/imm32/disp32-is-first-inout
31181     0/imm32/no-xm32
31182     0/imm32/no-x32
31183     0x11/imm32/alloc-id:fake
31184     _Primitive-break-if-float<=-named/imm32/next
31185 _Primitive-break-if-float<=-named:  # (payload primitive)
31186     0x11/imm32/alloc-id:fake:payload
31187     0x11/imm32/alloc-id:fake
31188     _string-break-if-float<=/imm32/name
31189     0x11/imm32/alloc-id:fake
31190     Single-lit-var/imm32/inouts
31191     0/imm32/no-outputs
31192     0/imm32/no-outputs
31193     0x11/imm32/alloc-id:fake
31194     _string_0f_86_jump_label/imm32/subx-name
31195     0/imm32/no-rm32
31196     0/imm32/no-r32
31197     0/imm32/no-imm32
31198     0/imm32/no-imm8
31199     1/imm32/disp32-is-first-inout
31200     0/imm32/no-xm32
31201     0/imm32/no-x32
31202     0x11/imm32/alloc-id:fake
31203     _Primitive-break-if-float>-named/imm32/next
31204 _Primitive-break-if-float>-named:  # (payload primitive)
31205     0x11/imm32/alloc-id:fake:payload
31206     0x11/imm32/alloc-id:fake
31207     _string-break-if-float>/imm32/name
31208     0x11/imm32/alloc-id:fake
31209     Single-lit-var/imm32/inouts
31210     0/imm32/no-outputs
31211     0/imm32/no-outputs
31212     0x11/imm32/alloc-id:fake
31213     _string_0f_87_jump_label/imm32/subx-name
31214     0/imm32/no-rm32
31215     0/imm32/no-r32
31216     0/imm32/no-imm32
31217     0/imm32/no-imm8
31218     1/imm32/disp32-is-first-inout
31219     0/imm32/no-xm32
31220     0/imm32/no-x32
31221     0x11/imm32/alloc-id:fake
31222     _Primitive-loop-if-float<-named/imm32/next
31223 _Primitive-loop-if-float<-named:  # (payload primitive)
31224     0x11/imm32/alloc-id:fake:payload
31225     0x11/imm32/alloc-id:fake
31226     _string-loop-if-float</imm32/name
31227     0x11/imm32/alloc-id:fake
31228     Single-lit-var/imm32/inouts
31229     0/imm32/no-outputs
31230     0/imm32/no-outputs
31231     0x11/imm32/alloc-id:fake
31232     _string_0f_82_jump_label/imm32/subx-name
31233     0/imm32/no-rm32
31234     0/imm32/no-r32
31235     0/imm32/no-imm32
31236     0/imm32/no-imm8
31237     1/imm32/disp32-is-first-inout
31238     0/imm32/no-xm32
31239     0/imm32/no-x32
31240     0x11/imm32/alloc-id:fake
31241     _Primitive-loop-if-float>=-named/imm32/next
31242 _Primitive-loop-if-float>=-named:  # (payload primitive)
31243     0x11/imm32/alloc-id:fake:payload
31244     0x11/imm32/alloc-id:fake
31245     _string-loop-if-float>=/imm32/name
31246     0x11/imm32/alloc-id:fake
31247     Single-lit-var/imm32/inouts
31248     0/imm32/no-outputs
31249     0/imm32/no-outputs
31250     0x11/imm32/alloc-id:fake
31251     _string_0f_83_jump_label/imm32/subx-name
31252     0/imm32/no-rm32
31253     0/imm32/no-r32
31254     0/imm32/no-imm32
31255     0/imm32/no-imm8
31256     1/imm32/disp32-is-first-inout
31257     0/imm32/no-xm32
31258     0/imm32/no-x32
31259     0x11/imm32/alloc-id:fake
31260     _Primitive-loop-if-float<=-named/imm32/next
31261 _Primitive-loop-if-float<=-named:  # (payload primitive)
31262     0x11/imm32/alloc-id:fake:payload
31263     0x11/imm32/alloc-id:fake
31264     _string-loop-if-float<=/imm32/name
31265     0x11/imm32/alloc-id:fake
31266     Single-lit-var/imm32/inouts
31267     0/imm32/no-outputs
31268     0/imm32/no-outputs
31269     0x11/imm32/alloc-id:fake
31270     _string_0f_86_jump_label/imm32/subx-name
31271     0/imm32/no-rm32
31272     0/imm32/no-r32
31273     0/imm32/no-imm32
31274     0/imm32/no-imm8
31275     1/imm32/disp32-is-first-inout
31276     0/imm32/no-xm32
31277     0/imm32/no-x32
31278     0x11/imm32/alloc-id:fake
31279     _Primitive-loop-if-float>-named/imm32/next
31280 _Primitive-loop-if-float>-named:  # (payload primitive)
31281     0x11/imm32/alloc-id:fake:payload
31282     0x11/imm32/alloc-id:fake
31283     _string-loop-if-float>/imm32/name
31284     0x11/imm32/alloc-id:fake
31285     Single-lit-var/imm32/inouts
31286     0/imm32/no-outputs
31287     0/imm32/no-outputs
31288     0x11/imm32/alloc-id:fake
31289     _string_0f_87_jump_label/imm32/subx-name
31290     0/imm32/no-rm32
31291     0/imm32/no-r32
31292     0/imm32/no-imm32
31293     0/imm32/no-imm8
31294     1/imm32/disp32-is-first-inout
31295     0/imm32/no-xm32
31296     0/imm32/no-x32
31297     0/imm32/next
31298     0/imm32/next
31299 
31300 # string literals for Mu instructions
31301 _string-add:  # (payload array byte)
31302     0x11/imm32/alloc-id:fake:payload
31303     # "add"
31304     0x3/imm32/size
31305     0x61/a 0x64/d 0x64/d
31306 _string-address:  # (payload array byte)
31307     0x11/imm32/alloc-id:fake:payload
31308     # "address"
31309     0x7/imm32/size
31310     0x61/a 0x64/d 0x64/d 0x72/r 0x65/e 0x73/s 0x73/s
31311 _string-add-to:  # (payload array byte)
31312     0x11/imm32/alloc-id:fake:payload
31313     # "add-to"
31314     0x6/imm32/size
31315     0x61/a 0x64/d 0x64/d 0x2d/dash 0x74/t 0x6f/o
31316 _string-and:  # (payload array byte)
31317     0x11/imm32/alloc-id:fake:payload
31318     # "and"
31319     0x3/imm32/size
31320     0x61/a 0x6e/n 0x64/d
31321 _string-and-with:  # (payload array byte)
31322     0x11/imm32/alloc-id:fake:payload
31323     # "and-with"
31324     0x8/imm32/size
31325     0x61/a 0x6e/n 0x64/d 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
31326 _string-break:  # (payload array byte)
31327     0x11/imm32/alloc-id:fake:payload
31328     # "break"
31329     0x5/imm32/size
31330     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k
31331 _string-break-if-<:  # (payload array byte)
31332     0x11/imm32/alloc-id:fake:payload
31333     # "break-if-<"
31334     0xa/imm32/size
31335     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/<
31336 _string-break-if-<=:  # (payload array byte)
31337     0x11/imm32/alloc-id:fake:payload
31338     # "break-if-<="
31339     0xb/imm32/size
31340     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< 0x3d/=
31341 _string-break-if-=:  # (payload array byte)
31342     0x11/imm32/alloc-id:fake:payload
31343     # "break-if-="
31344     0xa/imm32/size
31345     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3d/=
31346 _string-break-if->:  # (payload array byte)
31347     0x11/imm32/alloc-id:fake:payload
31348     # "break-if->"
31349     0xa/imm32/size
31350     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/>
31351 _string-break-if->=:  # (payload array byte)
31352     0x11/imm32/alloc-id:fake:payload
31353     # "break-if->="
31354     0xb/imm32/size
31355     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> 0x3d/=
31356 _string-break-if-!=:  # (payload array byte)
31357     0x11/imm32/alloc-id:fake:payload
31358     # "break-if-!="
31359     0xb/imm32/size
31360     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x21/! 0x3d/=
31361 _string-break-if-addr<:  # (payload array byte)
31362     0x11/imm32/alloc-id:fake:payload
31363     # "break-if-addr<"
31364     0xe/imm32/size
31365     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3c/<
31366 _string-break-if-addr<=:  # (payload array byte)
31367     0x11/imm32/alloc-id:fake:payload
31368     # "break-if-addr<="
31369     0xf/imm32/size
31370     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3c/< 0x3d/=
31371 _string-break-if-addr>:  # (payload array byte)
31372     0x11/imm32/alloc-id:fake:payload
31373     # "break-if-addr>"
31374     0xe/imm32/size
31375     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3e/>
31376 _string-break-if-addr>=:  # (payload array byte)
31377     0x11/imm32/alloc-id:fake:payload
31378     # "break-if-addr>="
31379     0xf/imm32/size
31380     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3e/> 0x3d/=
31381 _string-break-if-float<:  # (payload array byte)
31382     0x11/imm32/alloc-id:fake:payload
31383     # "break-if-float<"
31384     0xf/imm32/size
31385     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x66/f 0x6c/l 0x6f/o 0x61/a 0x74/t 0x3c/<
31386 _string-break-if-float<=:  # (payload array byte)
31387     0x11/imm32/alloc-id:fake:payload
31388     # "break-if-float<="
31389     0x10/imm32/size
31390     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x66/f 0x6c/l 0x6f/o 0x61/a 0x74/t 0x3c/< 0x3d/=
31391 _string-break-if-float>:  # (payload array byte)
31392     0x11/imm32/alloc-id:fake:payload
31393     # "break-if-float>"
31394     0xf/imm32/size
31395     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x66/f 0x6c/l 0x6f/o 0x61/a 0x74/t 0x3e/>
31396 _string-break-if-float>=:  # (payload array byte)
31397     0x11/imm32/alloc-id:fake:payload
31398     # "break-if-float>="
31399     0x10/imm32/size
31400     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x66/f 0x6c/l 0x6f/o 0x61/a 0x74/t 0x3e/> 0x3d/=
31401 _string-compare:  # (payload array byte)
31402     0x11/imm32/alloc-id:fake:payload
31403     # "compare"
31404     0x7/imm32/size
31405     0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e
31406 _string-copy:  # (payload array byte)
31407     0x11/imm32/alloc-id:fake:payload
31408     # "copy"
31409     0x4/imm32/size
31410     0x63/c 0x6f/o 0x70/p 0x79/y
31411 _string-copy-to:  # (payload array byte)
31412     0x11/imm32/alloc-id:fake:payload
31413     # "copy-to"
31414     0x7/imm32/size
31415     0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x74/t 0x6f/o
31416 _string-copy-byte:
31417     0x11/imm32/alloc-id:fake:payload
31418     # "copy-byte"
31419     0x9/imm32/size
31420     0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/- 0x62/b 0x79/y 0x74/t 0x65/e
31421 _string-copy-byte-to:
31422     0x11/imm32/alloc-id:fake:payload
31423     # "copy-byte-to"
31424     0xc/imm32/size
31425     0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/- 0x62/b 0x79/y 0x74/t 0x65/e 0x2d/- 0x74/t 0x6f/o
31426 _string-decrement:  # (payload array byte)
31427     0x11/imm32/alloc-id:fake:payload
31428     # "decrement"
31429     0x9/imm32/size
31430     0x64/d 0x65/e 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t
31431 _string-increment:  # (payload array byte)
31432     0x11/imm32/alloc-id:fake:payload
31433     # "increment"
31434     0x9/imm32/size
31435     0x69/i 0x6e/n 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t
31436 _string-loop:  # (payload array byte)
31437     0x11/imm32/alloc-id:fake:payload
31438     # "loop"
31439     0x4/imm32/size
31440     0x6c/l 0x6f/o 0x6f/o 0x70/p
31441 _string-loop-if-<:  # (payload array byte)
31442     0x11/imm32/alloc-id:fake:payload
31443     # "loop-if-<"
31444     0x9/imm32/size
31445     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/<
31446 _string-loop-if-<=:  # (payload array byte)
31447     0x11/imm32/alloc-id:fake:payload
31448     # "loop-if-<="
31449     0xa/imm32/size
31450     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< 0x3d/=
31451 _string-loop-if-=:  # (payload array byte)
31452     0x11/imm32/alloc-id:fake:payload
31453     # "loop-if-="
31454     0x9/imm32/size
31455     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3d/=
31456 _string-loop-if->:  # (payload array byte)
31457     0x11/imm32/alloc-id:fake:payload
31458     # "loop-if->"
31459     0x9/imm32/size
31460     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/>
31461 _string-loop-if->=:  # (payload array byte)
31462     0x11/imm32/alloc-id:fake:payload
31463     # "loop-if->="
31464     0xa/imm32/size
31465     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> 0x3d/=
31466 _string-loop-if-!=:  # (payload array byte)
31467     0x11/imm32/alloc-id:fake:payload
31468     # "loop-if-!="
31469     0xa/imm32/size
31470     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x21/! 0x3d/=
31471 _string-loop-if-addr<:  # (payload array byte)
31472     0x11/imm32/alloc-id:fake:payload
31473     # "loop-if-addr<"
31474     0xd/imm32/size
31475     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3c/<
31476 _string-loop-if-addr<=:  # (payload array byte)
31477     0x11/imm32/alloc-id:fake:payload
31478     # "loop-if-addr<="
31479     0xe/imm32/size
31480     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3c/< 0x3d/=
31481 _string-loop-if-addr>:  # (payload array byte)
31482     0x11/imm32/alloc-id:fake:payload
31483     # "loop-if-addr>"
31484     0xd/imm32/size
31485     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3e/>
31486 _string-loop-if-addr>=:  # (payload array byte)
31487     0x11/imm32/alloc-id:fake:payload
31488     # "loop-if-addr>="
31489     0xe/imm32/size
31490     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3e/> 0x3d/=
31491 _string-loop-if-float<:  # (payload array byte)
31492     0x11/imm32/alloc-id:fake:payload
31493     # "loop-if-float<"
31494     0xe/imm32/size
31495     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x66/f 0x6c/l 0x6f/o 0x61/a 0x74/t 0x3c/<
31496 _string-loop-if-float<=:  # (payload array byte)
31497     0x11/imm32/alloc-id:fake:payload
31498     # "loop-if-float<="
31499     0xf/imm32/size
31500     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x66/f 0x6c/l 0x6f/o 0x61/a 0x74/t 0x3c/< 0x3d/=
31501 _string-loop-if-float>:  # (payload array byte)
31502     0x11/imm32/alloc-id:fake:payload
31503     # "loop-if-float>"
31504     0xe/imm32/size
31505     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x66/f 0x6c/l 0x6f/o 0x61/a 0x74/t 0x3e/>
31506 _string-loop-if-float>=:  # (payload array byte)
31507     0x11/imm32/alloc-id:fake:payload
31508     # "loop-if-float>="
31509     0xf/imm32/size
31510     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x66/f 0x6c/l 0x6f/o 0x61/a 0x74/t 0x3e/> 0x3d/=
31511 _string-multiply:  # (payload array byte)
31512     0x11/imm32/alloc-id:fake:payload
31513     # "multiply"
31514     0x8/imm32/size
31515     0x6d/m 0x75/u 0x6c/l 0x74/t 0x69/i 0x70/p 0x6c/l 0x79/y
31516 _string-convert:  # (payload array byte)
31517     0x11/imm32/alloc-id:fake:payload
31518     # "convert"
31519     0x7/imm32/size
31520     0x63/c 0x6f/o 0x6e/n 0x76/v 0x65/e 0x72/r 0x74/t
31521 _string-truncate:  # (payload array byte)
31522     0x11/imm32/alloc-id:fake:payload
31523     # "truncate"
31524     0x8/imm32/size
31525     0x74/t 0x72/r 0x75/u 0x6e/n 0x63/c 0x61/a 0x74/t 0x65/e
31526 _string-reinterpret:  # (payload array byte)
31527     0x11/imm32/alloc-id:fake:payload
31528     # "reinterpret"
31529     0xb/imm32/size
31530     0x72/r 0x65/e 0x69/i 0x6e/n 0x74/t 0x65/e 0x72/r 0x70/p 0x72/r 0x65/e 0x74/t
31531 _string-divide:
31532     0x11/imm32/alloc-id:fake:payload
31533     # "divide"
31534     0x6/imm32/size
31535     0x64/d 0x69/i 0x76/v 0x69/i 0x64/d 0x65/e
31536 _string-max:
31537     0x11/imm32/alloc-id:fake:payload
31538     # "max"
31539     0x3/imm32/size
31540     0x6d/m 0x61/a 0x78/x
31541 _string-min:
31542     0x11/imm32/alloc-id:fake:payload
31543     # "min"
31544     0x3/imm32/size
31545     0x6d/m 0x69/i 0x6e/n
31546 _string-reciprocal:
31547     0x11/imm32/alloc-id:fake:payload
31548     # "reciprocal"
31549     0xa/imm32/size
31550     0x72/r 0x65/e 0x63/c 0x69/i 0x70/p 0x72/r 0x6f/o 0x63/c 0x61/a 0x6c/l
31551 _string-square-root:
31552     0x11/imm32/alloc-id:fake:payload
31553     # "square-root"
31554     0xb/imm32/size
31555     0x73/s 0x71/q 0x75/u 0x61/a 0x72/r 0x65/e 0x2d/- 0x72/r 0x6f/o 0x6f/o 0x74/t
31556 _string-inverse-square-root:
31557     0x11/imm32/alloc-id:fake:payload
31558     # "inverse-square-root"
31559     0x13/imm32/size
31560     0x69/i 0x6e/n 0x76/v 0x65/e 0x72/r 0x73/s 0x65/e 0x2d/- 0x73/s 0x71/q 0x75/u 0x61/a 0x72/r 0x65/e 0x2d/- 0x72/r 0x6f/o 0x6f/o 0x74/t
31561 _string-negate:  # (payload array byte)
31562     0x11/imm32/alloc-id:fake:payload
31563     # "negate"
31564     0x6/imm32/size
31565     0x6e/n 0x65/e 0x67/g 0x61/a 0x74/t 0x65/e
31566 _string-or:  # (payload array byte)
31567     0x11/imm32/alloc-id:fake:payload
31568     # "or"
31569     0x2/imm32/size
31570     0x6f/o 0x72/r
31571 _string-or-with:  # (payload array byte)
31572     0x11/imm32/alloc-id:fake:payload
31573     # "or-with"
31574     0x7/imm32/size
31575     0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
31576 _string-subtract:  # (payload array byte)
31577     0x11/imm32/alloc-id:fake:payload
31578     # "subtract"
31579     0x8/imm32/size
31580     0x73/s 0x75/u 0x62/b 0x74/t 0x72/r 0x61/a 0x63/c 0x74/t
31581 _string-subtract-from:  # (payload array byte)
31582     0x11/imm32/alloc-id:fake:payload
31583     # "subtract-from"
31584     0xd/imm32/size
31585     0x73/s 0x75/u 0x62/b 0x74/t 0x72/r 0x61/a 0x63/c 0x74/t 0x2d/dash 0x66/f 0x72/r 0x6f/o 0x6d/m
31586 _string-xor:  # (payload array byte)
31587     0x11/imm32/alloc-id:fake:payload
31588     # "xor"
31589     0x3/imm32/size
31590     0x78/x 0x6f/o 0x72/r
31591 _string-xor-with:  # (payload array byte)
31592     0x11/imm32/alloc-id:fake:payload
31593     # "xor-with"
31594     0x8/imm32/size
31595     0x78/x 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
31596 _string-shift-left:  # (payload array byte)
31597     0x11/imm32/alloc-id:fake:payload
31598     # "shift-left"
31599     0xa/imm32/size
31600     0x73/s 0x68/h 0x69/i 0x66/f 0x74/t 0x2d/dash 0x6c/l 0x65/e 0x66/f 0x74/t
31601 _string-shift-right:  # (payload array byte)
31602     0x11/imm32/alloc-id:fake:payload
31603     # "shift-right"
31604     0xb/imm32/size
31605     0x73/s 0x68/h 0x69/i 0x66/f 0x74/t 0x2d/dash 0x72/r 0x69/i 0x67/g 0x68/h 0x74/t
31606 _string-shift-right-signed:  # (payload array byte)
31607     0x11/imm32/alloc-id:fake:payload
31608     # "shift-right-signed"
31609     0x12/imm32/size
31610     0x73/s 0x68/h 0x69/i 0x66/f 0x74/t 0x2d/dash 0x72/r 0x69/i 0x67/g 0x68/h 0x74/t 0x2d/dash 0x73/s 0x69/i 0x67/g 0x6e/n 0x65/e 0x64/d
31611 
31612 # string literals for SubX instructions
31613 _string_01_add_to:  # (payload array byte)
31614     0x11/imm32/alloc-id:fake:payload
31615     # "01/add-to"
31616     0x9/imm32/size
31617     0x30/0 0x31/1 0x2f/slash 0x61/a 0x64/d 0x64/d 0x2d/dash 0x74/t 0x6f/o
31618 _string_03_add:  # (payload array byte)
31619     0x11/imm32/alloc-id:fake:payload
31620     # "03/add"
31621     0x6/imm32/size
31622     0x30/0 0x33/3 0x2f/slash 0x61/a 0x64/d 0x64/d
31623 _string_05_add_to_eax:  # (payload array byte)
31624     0x11/imm32/alloc-id:fake:payload
31625     # "05/add-to-eax"
31626     0xd/imm32/size
31627     0x30/0 0x35/5 0x2f/slash 0x61/a 0x64/d 0x64/d 0x2d/dash 0x74/t 0x6f/o 0x2d/dash 0x65/e 0x61/a 0x78/x
31628 _string_09_or_with:  # (payload array byte)
31629     0x11/imm32/alloc-id:fake:payload
31630     # "09/or-with"
31631     0xa/imm32/size
31632     0x30/0 0x39/9 0x2f/slash 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
31633 _string_0b_or:  # (payload array byte)
31634     0x11/imm32/alloc-id:fake:payload
31635     # "0b/or"
31636     0x5/imm32/size
31637     0x30/0 0x62/b 0x2f/slash 0x6f/o 0x72/r
31638 _string_0d_or_with_eax:  # (payload array byte)
31639     0x11/imm32/alloc-id:fake:payload
31640     # "0d/or-with-eax"
31641     0xe/imm32/size
31642     0x30/0 0x64/d 0x2f/slash 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h 0x2d/dash 0x65/e 0x61/a 0x78/x
31643 _string_0f_82_jump_label:  # (payload array byte)
31644     0x11/imm32/alloc-id:fake:payload
31645     # "0f 82/jump-if-addr<"
31646     0x13/imm32/size
31647     0x30/0 0x66/f 0x20/space 0x38/8 0x32/2 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3c/<
31648 _string_0f_82_jump_break:  # (payload array byte)
31649     0x11/imm32/alloc-id:fake:payload
31650     # "0f 82/jump-if-addr< break/disp32"
31651     0x20/imm32/size
31652     0x30/0 0x66/f 0x20/space 0x38/8 0x32/2 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3c/< 0x20/space 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
31653 _string_0f_82_jump_loop:  # (payload array byte)
31654     0x11/imm32/alloc-id:fake:payload
31655     # "0f 82/jump-if-addr< loop/disp32"
31656     0x1f/imm32/size
31657     0x30/0 0x66/f 0x20/space 0x38/8 0x32/2 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3c/< 0x20/space 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
31658 _string_0f_83_jump_label:  # (payload array byte)
31659     0x11/imm32/alloc-id:fake:payload
31660     # "0f 83/jump-if-addr>="
31661     0x14/imm32/size
31662     0x30/0 0x66/f 0x20/space 0x38/8 0x33/3 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3e/> 0x3d/=
31663 _string_0f_83_jump_break:  # (payload array byte)
31664     0x11/imm32/alloc-id:fake:payload
31665     # "0f 83/jump-if-addr>= break/disp32"
31666     0x21/imm32/size
31667     0x30/0 0x66/f 0x20/space 0x38/8 0x33/3 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3e/> 0x3d/= 0x20/space 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
31668 _string_0f_83_jump_loop:  # (payload array byte)
31669     0x11/imm32/alloc-id:fake:payload
31670     # "0f 83/jump-if-addr>= loop/disp32"
31671     0x20/imm32/size
31672     0x30/0 0x66/f 0x20/space 0x38/8 0x33/3 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3e/> 0x3d/= 0x20/space 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
31673 _string_0f_84_jump_label:  # (payload array byte)
31674     0x11/imm32/alloc-id:fake:payload
31675     # "0f 84/jump-if-="
31676     0xf/imm32/size
31677     0x30/0 0x66/f 0x20/space 0x38/8 0x34/4 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3d/=
31678 _string_0f_84_jump_break:  # (payload array byte)
31679     0x11/imm32/alloc-id:fake:payload
31680     # "0f 84/jump-if-= break/disp32"
31681     0x1c/imm32/size
31682     0x30/0 0x66/f 0x20/space 0x38/8 0x34/4 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3d/= 0x20/space 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
31683 _string_0f_84_jump_loop:  # (payload array byte)
31684     0x11/imm32/alloc-id:fake:payload
31685     # "0f 84/jump-if-= loop/disp32"
31686     0x1b/imm32/size
31687     0x30/0 0x66/f 0x20/space 0x38/8 0x34/4 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3d/= 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
31688 _string_0f_85_jump_label:  # (payload array byte)
31689     0x11/imm32/alloc-id:fake:payload
31690     # "0f 85/jump-if-!="
31691     0x10/imm32/size
31692     0x30/0 0x66/f 0x20/space 0x38/8 0x35/5 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x21/! 0x3d/=
31693 _string_0f_85_jump_break:  # (payload array byte)
31694     0x11/imm32/alloc-id:fake:payload
31695     # "0f 85/jump-if-!= break/disp32"
31696     0x1d/imm32/size
31697     0x30/0 0x66/f 0x20/space 0x38/8 0x35/5 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x21/! 0x3d/= 0x20/space 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
31698 _string_0f_85_jump_loop:  # (payload array byte)
31699     0x11/imm32/alloc-id:fake:payload
31700     # "0f 85/jump-if-!= loop/disp32"
31701     0x1c/imm32/size
31702     0x30/0 0x66/f 0x20/space 0x38/8 0x35/5 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x21/! 0x3d/= 0x20/space 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
31703 _string_0f_86_jump_label:  # (payload array byte)
31704     0x11/imm32/alloc-id:fake:payload
31705     # "0f 86/jump-if-addr<="
31706     0x14/imm32/size
31707     0x30/0 0x66/f 0x20/space 0x38/8 0x36/6 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3c/< 0x3d/=
31708 _string_0f_86_jump_break:  # (payload array byte)
31709     0x11/imm32/alloc-id:fake:payload
31710     # "0f 86/jump-if-addr<= break/disp32"
31711     0x21/imm32/size
31712     0x30/0 0x66/f 0x20/space 0x38/8 0x36/6 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3c/< 0x3d/= 0x20/space 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
31713 _string_0f_86_jump_loop:  # (payload array byte)
31714     0x11/imm32/alloc-id:fake:payload
31715     # "0f 86/jump-if-addr<= loop/disp32"
31716     0x20/imm32/size
31717     0x30/0 0x66/f 0x20/space 0x38/8 0x36/6 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3c/< 0x3d/= 0x20/space 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
31718 _string_0f_87_jump_label:  # (payload array byte)
31719     0x11/imm32/alloc-id:fake:payload
31720     # "0f 87/jump-if-addr>"
31721     0x13/imm32/size
31722     0x30/0 0x66/f 0x20/space 0x38/8 0x37/7 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3e/>
31723 _string_0f_87_jump_break:  # (payload array byte)
31724     0x11/imm32/alloc-id:fake:payload
31725     # "0f 87/jump-if-addr> break/disp32"
31726     0x20/imm32/size
31727     0x30/0 0x66/f 0x20/space 0x38/8 0x37/7 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3e/> 0x20/space 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
31728 _string_0f_87_jump_loop:  # (payload array byte)
31729     0x11/imm32/alloc-id:fake:payload
31730     # "0f 87/jump-if-addr> loop/disp32"
31731     0x1f/imm32/size
31732     0x30/0 0x66/f 0x20/space 0x38/8 0x37/7 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3e/> 0x20/space 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
31733 _string_0f_8c_jump_label:  # (payload array byte)
31734     0x11/imm32/alloc-id:fake:payload
31735     # "0f 8c/jump-if-<"
31736     0xf/imm32/size
31737     0x30/0 0x66/f 0x20/space 0x38/8 0x63/c 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/<
31738 _string_0f_8c_jump_break:  # (payload array byte)
31739     0x11/imm32/alloc-id:fake:payload
31740     # "0f 8c/jump-if-< break/disp32"
31741     0x1c/imm32/size
31742     0x30/0 0x66/f 0x20/space 0x38/8 0x63/c 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< 0x20/space 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
31743 _string_0f_8c_jump_loop:  # (payload array byte)
31744     0x11/imm32/alloc-id:fake:payload
31745     # "0f 8c/jump-if-< loop/disp32"
31746     0x1b/imm32/size
31747     0x30/0 0x66/f 0x20/space 0x38/8 0x63/c 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< 0x20/space 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
31748 _string_0f_8d_jump_label:  # (payload array byte)
31749     0x11/imm32/alloc-id:fake:payload
31750     # "0f 8d/jump-if->="
31751     0x10/imm32/size
31752     0x30/0 0x66/f 0x20/space 0x38/8 0x64/d 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> 0x3d/=
31753 _string_0f_8d_jump_break:  # (payload array byte)
31754     0x11/imm32/alloc-id:fake:payload
31755     # "0f 8d/jump-if->= break/disp32"
31756     0x1d/imm32/size
31757     0x30/0 0x66/f 0x20/space 0x38/8 0x64/d 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> 0x3d/= 0x20/space 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
31758 _string_0f_8d_jump_loop:  # (payload array byte)
31759     0x11/imm32/alloc-id:fake:payload
31760     # "0f 8d/jump-if->= loop/disp32"
31761     0x1c/imm32/size
31762     0x30/0 0x66/f 0x20/space 0x38/8 0x64/d 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> 0x3d/= 0x20/space 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
31763 _string_0f_8e_jump_label:  # (payload array byte)
31764     0x11/imm32/alloc-id:fake:payload
31765     # "0f 8e/jump-if-<="
31766     0x10/imm32/size
31767     0x30/0 0x66/f 0x20/space 0x38/8 0x65/e 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< 0x3d/=
31768 _string_0f_8e_jump_break:  # (payload array byte)
31769     0x11/imm32/alloc-id:fake:payload
31770     # "0f 8e/jump-if-<= break/disp32"
31771     0x1d/imm32/size
31772     0x30/0 0x66/f 0x20/space 0x38/8 0x65/e 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< 0x3d/= 0x20/space 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
31773 _string_0f_8e_jump_loop:  # (payload array byte)
31774     0x11/imm32/alloc-id:fake:payload
31775     # "0f 8e/jump-if-<= loop/disp32"
31776     0x1c/imm32/size
31777     0x30/0 0x66/f 0x20/space 0x38/8 0x65/e 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< 0x3d/= 0x20/space 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
31778 _string_0f_8f_jump_label:  # (payload array byte)
31779     0x11/imm32/alloc-id:fake:payload
31780     # "0f 8f/jump-if->"
31781     0xf/imm32/size
31782     0x30/0 0x66/f 0x20/space 0x38/8 0x66/f 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/>
31783 _string_0f_8f_jump_break:  # (payload array byte)
31784     0x11/imm32/alloc-id:fake:payload
31785     # "0f 8f/jump-if-> break/disp32"
31786     0x1c/imm32/size
31787     0x30/0 0x66/f 0x20/space 0x38/8 0x66/f 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> 0x20/space 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
31788 _string_0f_8f_jump_loop:  # (payload array byte)
31789     0x11/imm32/alloc-id:fake:payload
31790     # "0f 8f/jump-if-> loop/disp32"
31791     0x1b/imm32/size
31792     0x30/0 0x66/f 0x20/space 0x38/8 0x66/f 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> 0x20/space 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
31793 _string_0f_af_multiply:  # (payload array byte)
31794     0x11/imm32/alloc-id:fake:payload
31795     # "0f af/multiply"
31796     0xe/imm32/size
31797     0x30/0 0x66/f 0x20/space 0x61/a 0x66/f 0x2f/slash 0x6d/m 0x75/u 0x6c/l 0x74/t 0x69/i 0x70/p 0x6c/l 0x79/y
31798 _string_f3_0f_2a_convert_to_float:
31799     0x11/imm32/alloc-id:fake:payload
31800     # "f3 0f 2a/convert-to-float"
31801     0x19/imm32/size
31802     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x32/2 0x61/a 0x2f/slash 0x63/c 0x6f/o 0x6e/n 0x76/v 0x65/e 0x72/r 0x74/t 0x2d/dash 0x74/t 0x6f/o 0x2d/dash 0x66/f 0x6c/l 0x6f/o 0x61/a 0x74/t
31803 _string_f3_0f_2d_convert_to_int:
31804     0x11/imm32/alloc-id:fake:payload
31805     # "f3 0f 2d/convert-to-int"
31806     0x17/imm32/size
31807     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x32/2 0x64/d 0x2f/slash 0x63/c 0x6f/o 0x6e/n 0x76/v 0x65/e 0x72/r 0x74/t 0x2d/dash 0x74/t 0x6f/o 0x2d/dash 0x69/i 0x6e/n 0x74/t
31808 _string_f3_0f_2c_truncate_to_int:
31809     0x11/imm32/alloc-id:fake:payload
31810     # "f3 0f 2c/truncate-to-int"
31811     0x18/imm32/size
31812     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x32/2 0x63/c 0x2f/slash 0x74/t 0x72/r 0x75/u 0x6e/n 0x63/c 0x61/a 0x74/t 0x65/e 0x2d/dash 0x74/t 0x6f/o 0x2d/dash 0x69/i 0x6e/n 0x74/t
31813 _string_f3_0f_58_add:
31814     0x11/imm32/alloc-id:fake:payload
31815     # "f3 0f 58/add"
31816     0xc/imm32/size
31817     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x38/8 0x2f/slash 0x61/a 0x64/d 0x64/d
31818 _string_f3_0f_5c_subtract:
31819     0x11/imm32/alloc-id:fake:payload
31820     # "f3 0f 5c/subtract"
31821     0x11/imm32/size
31822     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x63/c 0x2f/slash 0x73/s 0x75/u 0x62/b 0x74/t 0x72/r 0x61/a 0x63/c 0x74/t
31823 _string_f3_0f_59_multiply:
31824     0x11/imm32/alloc-id:fake:payload
31825     # "f3 0f 59/multiply"
31826     0x11/imm32/size
31827     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x39/9 0x2f/slash 0x6d/m 0x75/u 0x6c/l 0x74/t 0x69/i 0x70/p 0x6c/l 0x79/y
31828 _string_f3_0f_5e_divide:
31829     0x11/imm32/alloc-id:fake:payload
31830     # "f3 0f 5e/divide"
31831     0xf/imm32/size
31832     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x65/e 0x2f/slash 0x64/d 0x69/i 0x76/v 0x69/i 0x64/d 0x65/e
31833 _string_f3_0f_53_reciprocal:
31834     0x11/imm32/alloc-id:fake:payload
31835     # "f3 0f 53/reciprocal"
31836     0x13/imm32/size
31837     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x33/3 0x2f/slash 0x72/r 0x65/e 0x63/c 0x69/i 0x70/p 0x72/r 0x6f/o 0x63/c 0x61/a 0x6c/l
31838 _string_f3_0f_51_square_root:
31839     0x11/imm32/alloc-id:fake:payload
31840     # "f3 0f 51/square-root"
31841     0x14/imm32/size
31842     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x31/1 0x2f/slash 0x73/s 0x71/q 0x75/u 0x61/a 0x72/r 0x65/e 0x2d/dash 0x72/r 0x6f/o 0x6f/o 0x74/t
31843 _string_f3_0f_52_inverse_square_root:
31844     0x11/imm32/alloc-id:fake:payload
31845     # "f3 0f 52/inverse-square-root"
31846     0x1c/imm32/size
31847     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x32/2 0x2f/slash 0x69/i 0x6e/n 0x76/v 0x65/e 0x72/r 0x73/s 0x65/e 0x2d/dash 0x73/s 0x71/q 0x75/u 0x61/a 0x72/r 0x65/e 0x2d/dash 0x72/r 0x6f/o 0x6f/o 0x74/t
31848 _string_f3_0f_5d_min:
31849     0x11/imm32/alloc-id:fake:payload
31850     # "f3 0f 5d/min"
31851     0xc/imm32/size
31852     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x64/d 0x2f/slash 0x6d/m 0x69/i 0x6e/n
31853 _string_f3_0f_5f_max:
31854     0x11/imm32/alloc-id:fake:payload
31855     # "f3 0f 5f/max"
31856     0xc/imm32/size
31857     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x66/f 0x2f/slash 0x6d/m 0x61/a 0x78/x
31858 _string_f3_0f_10_copy:
31859     0x11/imm32/alloc-id:fake:payload
31860     # "f3 0f 10/copy"
31861     0xd/imm32/size
31862     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x31/1 0x30/0 0x2f/slash 0x63/c 0x6f/o 0x70/p 0x79/y
31863 _string_f3_0f_11_copy:
31864     0x11/imm32/alloc-id:fake:payload
31865     # "f3 0f 11/copy"
31866     0xd/imm32/size
31867     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x31/1 0x31/1 0x2f/slash 0x63/c 0x6f/o 0x70/p 0x79/y
31868 _string_0f_2f_compare:
31869     0x11/imm32/alloc-id:fake:payload
31870     # "0f 2f/compare"
31871     0xd/imm32/size
31872     0x30/0 0x66/f 0x20/space 0x32/2 0x66/f 0x2f/slash 0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e
31873 _string_21_and_with:  # (payload array byte)
31874     0x11/imm32/alloc-id:fake:payload
31875     # "21/and-with"
31876     0xb/imm32/size
31877     0x32/2 0x31/1 0x2f/slash 0x61/a 0x6e/n 0x64/d 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
31878 _string_23_and:  # (payload array byte)
31879     0x11/imm32/alloc-id:fake:payload
31880     # "23/and"
31881     0x6/imm32/size
31882     0x32/2 0x33/3 0x2f/slash 0x61/a 0x6e/n 0x64/d
31883 _string_25_and_with_eax:  # (payload array byte)
31884     0x11/imm32/alloc-id:fake:payload
31885     # "25/and-with-eax"
31886     0xf/imm32/size
31887     0x32/2 0x35/5 0x2f/slash 0x61/a 0x6e/n 0x64/d 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h 0x2d/dash 0x65/e 0x61/a 0x78/x
31888 _string_29_subtract_from:  # (payload array byte)
31889     0x11/imm32/alloc-id:fake:payload
31890     # "29/subtract-from"
31891     0x10/imm32/size
31892     0x32/2 0x39/9 0x2f/slash 0x73/s 0x75/u 0x62/b 0x74/t 0x72/r 0x61/a 0x63/c 0x74/t 0x2d/dash 0x66/f 0x72/r 0x6f/o 0x6d/m
31893 _string_2b_subtract:  # (payload array byte)
31894     0x11/imm32/alloc-id:fake:payload
31895     # "2b/subtract"
31896     0xb/imm32/size
31897     0x32/2 0x62/b 0x2f/slash 0x73/s 0x75/u 0x62/b 0x74/t 0x72/r 0x61/a 0x63/c 0x74/t
31898 _string_2d_subtract_from_eax:  # (payload array byte)
31899     0x11/imm32/alloc-id:fake:payload
31900     # "2d/subtract-from-eax"
31901     0x14/imm32/size
31902     0x32/2 0x64/d 0x2f/slash 0x73/s 0x75/u 0x62/b 0x74/t 0x72/r 0x61/a 0x63/c 0x74/t 0x2d/dash 0x66/f 0x72/r 0x6f/o 0x6d/m 0x2d/dash 0x65/e 0x61/a 0x78/x
31903 _string_31_xor_with:  # (payload array byte)
31904     0x11/imm32/alloc-id:fake:payload
31905     # "31/xor-with"
31906     0xb/imm32/size
31907     0x33/3 0x31/1 0x2f/slash 0x78/x 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
31908 _string_33_xor:  # (payload array byte)
31909     0x11/imm32/alloc-id:fake:payload
31910     # "33/xor"
31911     0x6/imm32/size
31912     0x33/3 0x33/3 0x2f/slash 0x78/x 0x6f/o 0x72/r
31913 _string_35_xor_with_eax:  # (payload array byte)
31914     0x11/imm32/alloc-id:fake:payload
31915     # "35/xor-with-eax"
31916     0xf/imm32/size
31917     0x33/3 0x35/5 0x2f/slash 0x78/x 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h 0x2d/dash 0x65/e 0x61/a 0x78/x
31918 _string_39_compare->:  # (payload array byte)
31919     0x11/imm32/alloc-id:fake:payload
31920     # "39/compare->"
31921     0xc/imm32/size
31922     0x33/3 0x39/9 0x2f/slash 0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e 0x2d/dash 0x3e/>
31923 _string_3b_compare<-:  # (payload array byte)
31924     0x11/imm32/alloc-id:fake:payload
31925     # "3b/compare<-"
31926     0xc/imm32/size
31927     0x33/3 0x62/b 0x2f/slash 0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e 0x3c/< 0x2d/dash
31928 _string_3d_compare_eax_with:  # (payload array byte)
31929     0x11/imm32/alloc-id:fake:payload
31930     # "3d/compare-eax-with"
31931     0x13/imm32/size
31932     0x33/3 0x64/d 0x2f/slash 0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e 0x2d/dash 0x65/e 0x61/a 0x78/x 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
31933 _string_40_increment_eax:  # (payload array byte)
31934     0x11/imm32/alloc-id:fake:payload
31935     # "40/increment-eax"
31936     0x10/imm32/size
31937     0x34/4 0x30/0 0x2f/slash 0x69/i 0x6e/n 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t 0x2d/dash 0x65/e 0x61/a 0x78/x
31938 _string_41_increment_ecx:  # (payload array byte)
31939     0x11/imm32/alloc-id:fake:payload
31940     # "41/increment-ecx"
31941     0x10/imm32/size
31942     0x34/4 0x31/1 0x2f/slash 0x69/i 0x6e/n 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t 0x2d/dash 0x65/e 0x63/c 0x78/x
31943 _string_42_increment_edx:  # (payload array byte)
31944     0x11/imm32/alloc-id:fake:payload
31945     # "42/increment-edx"
31946     0x10/imm32/size
31947     0x34/4 0x32/2 0x2f/slash 0x69/i 0x6e/n 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t 0x2d/dash 0x65/e 0x64/d 0x78/x
31948 _string_43_increment_ebx:  # (payload array byte)
31949     0x11/imm32/alloc-id:fake:payload
31950     # "43/increment-ebx"
31951     0x10/imm32/size
31952     0x34/4 0x33/3 0x2f/slash 0x69/i 0x6e/n 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t 0x2d/dash 0x65/e 0x62/b 0x78/x
31953 _string_46_increment_esi:  # (payload array byte)
31954     0x11/imm32/alloc-id:fake:payload
31955     # "46/increment-esi"
31956     0x10/imm32/size
31957     0x34/4 0x36/6 0x2f/slash 0x69/i 0x6e/n 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t 0x2d/dash 0x65/e 0x73/s 0x69/i
31958 _string_47_increment_edi:  # (payload array byte)
31959     0x11/imm32/alloc-id:fake:payload
31960     # "47/increment-edi"
31961     0x10/imm32/size
31962     0x34/4 0x37/7 0x2f/slash 0x69/i 0x6e/n 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t 0x2d/dash 0x65/e 0x64/d 0x69/i
31963 _string_48_decrement_eax:  # (payload array byte)
31964     0x11/imm32/alloc-id:fake:payload
31965     # "48/decrement-eax"
31966     0x10/imm32/size
31967     0x34/4 0x38/8 0x2f/slash 0x64/d 0x65/e 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t 0x2d/dash 0x65/e 0x61/a 0x78/x
31968 _string_49_decrement_ecx:  # (payload array byte)
31969     0x11/imm32/alloc-id:fake:payload
31970     # "49/decrement-ecx"
31971     0x10/imm32/size
31972     0x34/4 0x39/9 0x2f/slash 0x64/d 0x65/e 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t 0x2d/dash 0x65/e 0x63/c 0x78/x
31973 _string_4a_decrement_edx:  # (payload array byte)
31974     0x11/imm32/alloc-id:fake:payload
31975     # "4a/decrement-edx"
31976     0x10/imm32/size
31977     0x34/4 0x61/a 0x2f/slash 0x64/d 0x65/e 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t 0x2d/dash 0x65/e 0x64/d 0x78/x
31978 _string_4b_decrement_ebx:  # (payload array byte)
31979     0x11/imm32/alloc-id:fake:payload
31980     # "4b/decrement-ebx"
31981     0x10/imm32/size
31982     0x34/4 0x62/b 0x2f/slash 0x64/d 0x65/e 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t 0x2d/dash 0x65/e 0x62/b 0x78/x
31983 _string_4e_decrement_esi:  # (payload array byte)
31984     0x11/imm32/alloc-id:fake:payload
31985     # "4e/decrement-esi"
31986     0x10/imm32/size
31987     0x34/4 0x65/e 0x2f/slash 0x64/d 0x65/e 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t 0x2d/dash 0x65/e 0x73/s 0x69/i
31988 _string_4f_decrement_edi:  # (payload array byte)
31989     0x11/imm32/alloc-id:fake:payload
31990     # "4f/decrement-edi"
31991     0x10/imm32/size
31992     0x34/4 0x66/f 0x2f/slash 0x64/d 0x65/e 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t 0x2d/dash 0x65/e 0x64/d 0x69/i
31993 _string_81_subop_add:  # (payload array byte)
31994     0x11/imm32/alloc-id:fake:payload
31995     # "81 0/subop/add"
31996     0xe/imm32/size
31997     0x38/8 0x31/1 0x20/space 0x30/0 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x61/a 0x64/d 0x64/d
31998 _string_81_subop_or:  # (payload array byte)
31999     0x11/imm32/alloc-id:fake:payload
32000     # "81 1/subop/or"
32001     0xd/imm32/size
32002     0x38/8 0x31/1 0x20/space 0x31/1 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x6f/o 0x72/r
32003 _string_81_subop_and:  # (payload array byte)
32004     0x11/imm32/alloc-id:fake:payload
32005     # "81 4/subop/and"
32006     0xe/imm32/size
32007     0x38/8 0x31/1 0x20/space 0x34/4 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x61/a 0x6e/n 0x64/d
32008 _string_81_subop_subtract:  # (payload array byte)
32009     0x11/imm32/alloc-id:fake:payload
32010     # "81 5/subop/subtract"
32011     0x13/imm32/size
32012     0x38/8 0x31/1 0x20/space 0x35/5 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x73/s 0x75/u 0x62/b 0x74/t 0x72/r 0x61/a 0x63/c 0x74/t
32013 _string_81_subop_xor:  # (payload array byte)
32014     0x11/imm32/alloc-id:fake:payload
32015     # "81 6/subop/xor"
32016     0xe/imm32/size
32017     0x38/8 0x31/1 0x20/space 0x36/6 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x78/x 0x6f/o 0x72/r
32018 _string_81_subop_compare:  # (payload array byte)
32019     0x11/imm32/alloc-id:fake:payload
32020     # "81 7/subop/compare"
32021     0x12/imm32/size
32022     0x38/8 0x31/1 0x20/space 0x37/7 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e
32023 _string_89_<-:  # (payload array byte)
32024     0x11/imm32/alloc-id:fake:payload
32025     # "89/<-"
32026     0x5/imm32/size
32027     0x38/8 0x39/9 0x2f/slash 0x3c/< 0x2d/dash
32028 _string_8b_->:  # (payload array byte)
32029     0x11/imm32/alloc-id:fake:payload
32030     # "8b/->"
32031     0x5/imm32/size
32032     0x38/8 0x62/b 0x2f/slash 0x2d/dash 0x3e/>
32033 _string_8a_copy_byte:
32034     0x11/imm32/alloc-id:fake:payload
32035     # "8a/byte->"
32036     0x9/imm32/size
32037     0x38/8 0x61/a 0x2f// 0x62/b 0x79/y 0x74/t 0x65/e 0x2d/- 0x3e/>
32038 _string_88_copy_byte:
32039     0x11/imm32/alloc-id:fake:payload
32040     # "88/byte<-"
32041     0x9/imm32/size
32042     0x38/8 0x38/8 0x2f// 0x62/b 0x79/y 0x74/t 0x65/e 0x3c/< 0x2d/-
32043 _string_8d_copy_address:  # (payload array byte)
32044     0x11/imm32/alloc-id:fake:payload
32045     # "8d/copy-address"
32046     0xf/imm32/size
32047     0x38/8 0x64/d 0x2f/slash 0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x65/e 0x73/s 0x73/s
32048 _string_b8_copy_to_eax:  # (payload array byte)
32049     0x11/imm32/alloc-id:fake:payload
32050     # "b8/copy-to-eax"
32051     0xe/imm32/size
32052     0x62/b 0x38/8 0x2f/slash 0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x74/t 0x6f/o 0x2d/dash 0x65/e 0x61/a 0x78/x
32053 _string_b9_copy_to_ecx:  # (payload array byte)
32054     0x11/imm32/alloc-id:fake:payload
32055     # "b9/copy-to-ecx"
32056     0xe/imm32/size
32057     0x62/b 0x39/9 0x2f/slash 0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x74/t 0x6f/o 0x2d/dash 0x65/e 0x63/c 0x78/x
32058 _string_ba_copy_to_edx:  # (payload array byte)
32059     0x11/imm32/alloc-id:fake:payload
32060     # "ba/copy-to-edx"
32061     0xe/imm32/size
32062     0x62/b 0x61/a 0x2f/slash 0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x74/t 0x6f/o 0x2d/dash 0x65/e 0x64/d 0x78/x
32063 _string_bb_copy_to_ebx:  # (payload array byte)
32064     0x11/imm32/alloc-id:fake:payload
32065     # "bb/copy-to-ebx"
32066     0xe/imm32/size
32067     0x62/b 0x62/b 0x2f/slash 0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x74/t 0x6f/o 0x2d/dash 0x65/e 0x62/b 0x78/x
32068 _string_be_copy_to_esi:  # (payload array byte)
32069     0x11/imm32/alloc-id:fake:payload
32070     # "be/copy-to-esi"
32071     0xe/imm32/size
32072     0x62/b 0x65/e 0x2f/slash 0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x74/t 0x6f/o 0x2d/dash 0x65/e 0x73/s 0x69/i
32073 _string_bf_copy_to_edi:  # (payload array byte)
32074     0x11/imm32/alloc-id:fake:payload
32075     # "bf/copy-to-edi"
32076     0xe/imm32/size
32077     0x62/b 0x66/f 0x2f/slash 0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x74/t 0x6f/o 0x2d/dash 0x65/e 0x64/d 0x69/i
32078 _string_c7_subop_copy:  # (payload array byte)
32079     0x11/imm32/alloc-id:fake:payload
32080     # "c7 0/subop/copy"
32081     0xf/imm32/size
32082     0x63/c 0x37/7 0x20/space 0x30/0 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x63/c 0x6f/o 0x70/p 0x79/y
32083 _string_e9_jump_label:  # (payload array byte)
32084     0x11/imm32/alloc-id:fake:payload
32085     # "e9/jump"
32086     0x7/imm32/size
32087     0x65/e 0x39/9 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p
32088 _string_e9_jump_break:  # (payload array byte)
32089     0x11/imm32/alloc-id:fake:payload
32090     # "e9/jump break/disp32"
32091     0x14/imm32/size
32092     0x65/e 0x39/9 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x20/space 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
32093 _string_e9_jump_loop:  # (payload array byte)
32094     0x11/imm32/alloc-id:fake:payload
32095     # "e9/jump loop/disp32"
32096     0x13/imm32/size
32097     0x65/e 0x39/9 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x20/space 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
32098 _string_f7_subop_negate:
32099     0x11/imm32/alloc-id:fake:payload
32100     # "f7 3/subop/negate"
32101     0x11/imm32/size
32102     0x66/f 0x37/7 0x20/space 0x33/3 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x6e/n 0x65/e 0x67/g 0x61/a 0x74/t 0x65/e
32103 _string_ff_subop_increment:  # (payload array byte)
32104     0x11/imm32/alloc-id:fake:payload
32105     # "ff 0/subop/increment"
32106     0x14/imm32/size
32107     0x66/f 0x66/f 0x20/space 0x30/0 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x69/i 0x6e/n 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t
32108 _string_ff_subop_decrement:  # (payload array byte)
32109     0x11/imm32/alloc-id:fake:payload
32110     # "ff 1/subop/decrement"
32111     0x14/imm32/size
32112     0x66/f 0x66/f 0x20/space 0x31/1 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x65/e 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t
32113 _string_c1_subop_shift_left:  # (payload array byte)
32114     0x11/imm32/alloc-id:fake:payload
32115     # "c1/shift 4/subop/left"
32116     0x15/imm32/size
32117     0x63/c 0x31/1 0x2f/slash 0x73/s 0x68/h 0x69/i 0x66/f 0x74/t 0x20/space 0x34/4 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x6c/l 0x65/e 0x66/f 0x74/t
32118 _string_c1_subop_shift_right_padding_zeroes:  # (payload array byte)
32119     0x11/imm32/alloc-id:fake:payload
32120     # "c1/shift 5/subop/right-padding-zeroes"
32121     0x25/imm32/size
32122     0x63/c 0x31/1 0x2f/slash 0x73/s 0x68/h 0x69/i 0x66/f 0x74/t 0x20/space 0x35/5 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x72/r 0x69/i 0x67/g 0x68/h 0x74/t 0x2d/dash 0x70/p 0x61/a 0x64/d 0x64/d 0x69/i 0x6e/n 0x67/g 0x2d/dash 0x7a/z 0x65/e 0x72/r 0x6f/o 0x65/e 0x73/s
32123 _string_c1_subop_shift_right_preserving_sign:  # (payload array byte)
32124     0x11/imm32/alloc-id:fake:payload
32125     # "c1/shift 7/subop/right-preserving-sign"
32126     0x26/imm32/size
32127     0x63/c 0x31/1 0x2f/slash 0x73/s 0x68/h 0x69/i 0x66/f 0x74/t 0x20/space 0x37/7 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x72/r 0x69/i 0x67/g 0x68/h 0x74/t 0x2d/dash 0x70/p 0x72/r 0x65/e 0x73/s 0x65/e 0x72/r 0x76/v 0x69/i 0x6e/n 0x67/g 0x2d/dash 0x73/s 0x69/i 0x67/g 0x6e/n
32128 
32129 Single-int-var-in-mem:  # (payload list var)
32130     0x11/imm32/alloc-id:fake:payload
32131     0x11/imm32/alloc-id:fake
32132     Int-var-in-mem/imm32
32133     0/imm32/next
32134     0/imm32/next
32135 
32136 Int-var-in-mem:  # (payload var)
32137     0x11/imm32/alloc-id:fake:payload
32138     0/imm32/name
32139     0/imm32/name
32140     0x11/imm32/alloc-id:fake
32141     Type-int/imm32
32142     1/imm32/some-block-depth
32143     1/imm32/some-stack-offset
32144     0/imm32/no-register
32145     0/imm32/no-register
32146 
32147 # Not really legal, but closest we can currently represent a dereference of an (addr byte)
32148 Single-byte-var-in-mem:  # (payload list var)
32149     0x11/imm32/alloc-id:fake:payload
32150     0x11/imm32/alloc-id:fake
32151     Byte-var-in-mem/imm32
32152     0/imm32/next
32153     0/imm32/next
32154 
32155 # Not really legal, but closest we can currently represent a dereference of an (addr byte)
32156 Byte-var-in-mem:  # (payload var)
32157     0x11/imm32/alloc-id:fake:payload
32158     0/imm32/name
32159     0/imm32/name
32160     0x11/imm32/alloc-id:fake
32161     Type-byte/imm32
32162     1/imm32/some-block-depth
32163     1/imm32/some-stack-offset
32164     0/imm32/no-register
32165     0/imm32/no-register
32166 
32167 Two-args-int-stack-int-reg:  # (payload list var)
32168     0x11/imm32/alloc-id:fake:payload
32169     0x11/imm32/alloc-id:fake
32170     Int-var-in-mem/imm32
32171     0x11/imm32/alloc-id:fake
32172     Single-int-var-in-some-register/imm32/next
32173 
32174 Two-int-args-in-regs:  # (payload list var)
32175     0x11/imm32/alloc-id:fake:payload
32176     0x11/imm32/alloc-id:fake
32177     Int-var-in-some-register/imm32
32178     0x11/imm32/alloc-id:fake
32179     Single-int-var-in-some-register/imm32/next
32180 
32181 # Not really legal, but closest we can currently represent a dereference of an (addr byte)
32182 Two-args-byte-stack-byte-reg:  # (payload list var)
32183     0x11/imm32/alloc-id:fake:payload
32184     0x11/imm32/alloc-id:fake
32185     Byte-var-in-mem/imm32
32186     0x11/imm32/alloc-id:fake
32187     Single-byte-var-in-some-register/imm32/next
32188 
32189 Two-args-int-reg-int-stack:  # (payload list var)
32190     0x11/imm32/alloc-id:fake:payload
32191     0x11/imm32/alloc-id:fake
32192     Int-var-in-some-register/imm32
32193     0x11/imm32/alloc-id:fake
32194     Single-int-var-in-mem/imm32/next
32195 
32196 Two-args-int-eax-int-literal:  # (payload list var)
32197     0x11/imm32/alloc-id:fake:payload
32198     0x11/imm32/alloc-id:fake
32199     Int-var-in-eax/imm32
32200     0x11/imm32/alloc-id:fake
32201     Single-lit-var/imm32/next
32202 
32203 Int-var-and-literal:  # (payload list var)
32204     0x11/imm32/alloc-id:fake:payload
32205     0x11/imm32/alloc-id:fake
32206     Int-var-in-mem/imm32
32207     0x11/imm32/alloc-id:fake
32208     Single-lit-var/imm32/next
32209 
32210 Int-var-in-register-and-literal:  # (payload list var)
32211     0x11/imm32/alloc-id:fake:payload
32212     0x11/imm32/alloc-id:fake
32213     Int-var-in-some-register/imm32
32214     0x11/imm32/alloc-id:fake
32215     Single-lit-var/imm32/next
32216 
32217 Two-float-args-in-regs:  # (payload list var)
32218     0x11/imm32/alloc-id:fake:payload
32219     0x11/imm32/alloc-id:fake
32220     Float-var-in-some-register/imm32
32221     0x11/imm32/alloc-id:fake
32222     Single-float-var-in-some-register/imm32/next
32223 
32224 Two-args-float-reg-float-stack:  # (payload list var)
32225     0x11/imm32/alloc-id:fake:payload
32226     0x11/imm32/alloc-id:fake
32227     Float-var-in-some-register/imm32
32228     0x11/imm32/alloc-id:fake
32229     Single-float-var-in-mem/imm32/next
32230 
32231 Two-args-float-stack-float-reg:  # (payload list var)
32232     0x11/imm32/alloc-id:fake:payload
32233     0x11/imm32/alloc-id:fake
32234     Float-var-in-mem/imm32
32235     0x11/imm32/alloc-id:fake
32236     Single-float-var-in-some-register/imm32/next
32237 
32238 Single-int-var-in-some-register:  # (payload list var)
32239     0x11/imm32/alloc-id:fake:payload
32240     0x11/imm32/alloc-id:fake
32241     Int-var-in-some-register/imm32
32242     0/imm32/next
32243     0/imm32/next
32244 
32245 Single-addr-var-in-some-register:  # (payload list var)
32246     0x11/imm32/alloc-id:fake:payload
32247     0x11/imm32/alloc-id:fake
32248     Addr-var-in-some-register/imm32
32249     0/imm32/next
32250     0/imm32/next
32251 
32252 Single-byte-var-in-some-register:  # (payload list var)
32253     0x11/imm32/alloc-id:fake:payload
32254     0x11/imm32/alloc-id:fake
32255     Byte-var-in-some-register/imm32
32256     0/imm32/next
32257     0/imm32/next
32258 
32259 Int-var-in-some-register:  # (payload var)
32260     0x11/imm32/alloc-id:fake:payload
32261     0/imm32/name
32262     0/imm32/name
32263     0x11/imm32/alloc-id:fake
32264     Type-int/imm32
32265     1/imm32/some-block-depth
32266     0/imm32/no-stack-offset
32267     0x11/imm32/alloc-id:fake
32268     Any-register/imm32
32269 
32270 Any-register:  # (payload array byte)
32271     0x11/imm32/alloc-id:fake:payload
32272     1/imm32/size
32273     # data
32274     2a/asterisk
32275 
32276 Addr-var-in-some-register:  # (payload var)
32277     0x11/imm32/alloc-id:fake:payload
32278     0/imm32/name
32279     0/imm32/name
32280     0x11/imm32/alloc-id:fake
32281     Type-addr/imm32
32282     1/imm32/some-block-depth
32283     0/imm32/no-stack-offset
32284     0x11/imm32/alloc-id:fake
32285     Any-register/imm32
32286 
32287 Byte-var-in-some-register:  # (payload var)
32288     0x11/imm32/alloc-id:fake:payload
32289     0/imm32/name
32290     0/imm32/name
32291     0x11/imm32/alloc-id:fake
32292     Type-byte/imm32
32293     1/imm32/some-block-depth
32294     0/imm32/no-stack-offset
32295     0x11/imm32/alloc-id:fake
32296     Any-register/imm32
32297 
32298 Single-int-var-in-eax:  # (payload list var)
32299     0x11/imm32/alloc-id:fake:payload
32300     0x11/imm32/alloc-id:fake
32301     Int-var-in-eax/imm32
32302     0/imm32/next
32303     0/imm32/next
32304 
32305 Int-var-in-eax:
32306     0x11/imm32/alloc-id:fake:payload
32307     0/imm32/name
32308     0/imm32/name
32309     0x11/imm32/alloc-id:fake
32310     Type-int/imm32
32311     1/imm32/some-block-depth
32312     0/imm32/no-stack-offset
32313     0x11/imm32/alloc-id:fake
32314     $Mu-register-eax/imm32  # can't use Register-eax only to keep our buggy tools/treeshake.cc happy (TODO)
32315 
32316 Single-int-var-in-ecx:  # (payload list var)
32317     0x11/imm32/alloc-id:fake:payload
32318     0x11/imm32/alloc-id:fake
32319     Int-var-in-ecx/imm32
32320     0/imm32/next
32321     0/imm32/next
32322 
32323 Int-var-in-ecx:
32324     0x11/imm32/alloc-id:fake:payload
32325     0/imm32/name
32326     0/imm32/name
32327     0x11/imm32/alloc-id:fake
32328     Type-int/imm32
32329     1/imm32/some-block-depth
32330     0/imm32/no-stack-offset
32331     0x11/imm32/alloc-id:fake
32332     $Register-ecx/imm32/register
32333 
32334 Single-int-var-in-edx:  # (payload list var)
32335     0x11/imm32/alloc-id:fake:payload
32336     0x11/imm32/alloc-id:fake
32337     Int-var-in-edx/imm32
32338     0/imm32/next
32339     0/imm32/next
32340 
32341 Int-var-in-edx:  # (payload list var)
32342     0x11/imm32/alloc-id:fake:payload
32343     0/imm32/name
32344     0/imm32/name
32345     0x11/imm32/alloc-id:fake
32346     Type-int/imm32
32347     1/imm32/some-block-depth
32348     0/imm32/no-stack-offset
32349     0x11/imm32/alloc-id:fake
32350     $Register-edx/imm32/register
32351 
32352 Single-int-var-in-ebx:  # (payload list var)
32353     0x11/imm32/alloc-id:fake:payload
32354     0x11/imm32/alloc-id:fake
32355     Int-var-in-ebx/imm32
32356     0/imm32/next
32357     0/imm32/next
32358 
32359 Int-var-in-ebx:  # (payload list var)
32360     0x11/imm32/alloc-id:fake:payload
32361     0/imm32/name
32362     0/imm32/name
32363     0x11/imm32/alloc-id:fake
32364     Type-int/imm32
32365     1/imm32/some-block-depth
32366     0/imm32/no-stack-offset
32367     0x11/imm32/alloc-id:fake
32368     $Register-ebx/imm32/register
32369 
32370 Single-int-var-in-esi:  # (payload list var)
32371     0x11/imm32/alloc-id:fake:payload
32372     0x11/imm32/alloc-id:fake
32373     Int-var-in-esi/imm32
32374     0/imm32/next
32375     0/imm32/next
32376 
32377 Int-var-in-esi:  # (payload list var)
32378     0x11/imm32/alloc-id:fake:payload
32379     0/imm32/name
32380     0/imm32/name
32381     0x11/imm32/alloc-id:fake
32382     Type-int/imm32
32383     1/imm32/some-block-depth
32384     0/imm32/no-stack-offset
32385     0x11/imm32/alloc-id:fake
32386     $Register-esi/imm32/register
32387 
32388 Single-int-var-in-edi:  # (payload list var)
32389     0x11/imm32/alloc-id:fake:payload
32390     0x11/imm32/alloc-id:fake
32391     Int-var-in-edi/imm32
32392     0/imm32/next
32393     0/imm32/next
32394 
32395 Int-var-in-edi:  # (payload list var)
32396     0x11/imm32/alloc-id:fake:payload
32397     0/imm32/name
32398     0/imm32/name
32399     0x11/imm32/alloc-id:fake
32400     Type-int/imm32
32401     1/imm32/some-block-depth
32402     0/imm32/no-stack-offset
32403     0x11/imm32/alloc-id:fake
32404     $Register-edi/imm32/register
32405 
32406 Single-lit-var:  # (payload list var)
32407     0x11/imm32/alloc-id:fake:payload
32408     0x11/imm32/alloc-id:fake
32409     Lit-var/imm32
32410     0/imm32/next
32411     0/imm32/next
32412 
32413 Lit-var:  # (payload var)
32414     0x11/imm32/alloc-id:fake:payload
32415     0/imm32/name
32416     0/imm32/name
32417     0x11/imm32/alloc-id:fake
32418     Type-literal/imm32
32419     1/imm32/some-block-depth
32420     0/imm32/no-stack-offset
32421     0/imm32/no-register
32422     0/imm32/no-register
32423 
32424 Single-float-var-in-mem:  # (payload list var)
32425     0x11/imm32/alloc-id:fake:payload
32426     0x11/imm32/alloc-id:fake
32427     Float-var-in-mem/imm32
32428     0/imm32/next
32429     0/imm32/next
32430 
32431 Float-var-in-mem:  # (payload var)
32432     0x11/imm32/alloc-id:fake:payload
32433     0/imm32/name
32434     0/imm32/name
32435     0x11/imm32/alloc-id:fake
32436     Type-float/imm32
32437     1/imm32/some-block-depth
32438     1/imm32/some-stack-offset
32439     0/imm32/no-register
32440     0/imm32/no-register
32441 
32442 Single-float-var-in-some-register:  # (payload list var)
32443     0x11/imm32/alloc-id:fake:payload
32444     0x11/imm32/alloc-id:fake
32445     Float-var-in-some-register/imm32
32446     0/imm32/next
32447     0/imm32/next
32448 
32449 Float-var-in-some-register:  # (payload var)
32450     0x11/imm32/alloc-id:fake:payload
32451     0/imm32/name
32452     0/imm32/name
32453     0x11/imm32/alloc-id:fake
32454     Type-float/imm32
32455     1/imm32/some-block-depth
32456     0/imm32/no-stack-offset
32457     0x11/imm32/alloc-id:fake
32458     Any-register/imm32
32459 
32460 Type-int:  # (payload type-tree)
32461     0x11/imm32/alloc-id:fake:payload
32462     1/imm32/is-atom
32463     1/imm32/value:int
32464     0/imm32/left:unused
32465     0/imm32/right:null
32466     0/imm32/right:null
32467 
32468 Type-literal:  # (payload type-tree)
32469     0x11/imm32/alloc-id:fake:payload
32470     1/imm32/is-atom
32471     0/imm32/value:literal
32472     0/imm32/left:unused
32473     0/imm32/right:null
32474     0/imm32/right:null
32475 
32476 Type-addr:  # (payload type-tree)
32477     0x11/imm32/alloc-id:fake:payload
32478     1/imm32/is-atom
32479     2/imm32/value:addr
32480     0/imm32/left:unused
32481     0/imm32/right:null
32482     0/imm32/right:null
32483 
32484 Type-byte:  # (payload type-tree)
32485     0x11/imm32/alloc-id:fake:payload
32486     1/imm32/is-atom
32487     8/imm32/value:byte
32488     0/imm32/left:unused
32489     0/imm32/right:null
32490     0/imm32/right:null
32491 
32492 Type-float:  # (payload type-tree)
32493     0x11/imm32/alloc-id:fake:payload
32494     1/imm32/is-atom
32495     0xf/imm32/value:float
32496     0/imm32/left:unused
32497     0/imm32/right:null
32498     0/imm32/right:null
32499 
32500 == code
32501 emit-subx-primitive:  # out: (addr buffered-file), stmt: (addr stmt), primitive: (addr primitive), err: (addr buffered-file), ed: (addr exit-descriptor)
32502     # . prologue
32503     55/push-ebp
32504     89/<- %ebp 4/r32/esp
32505     # . save registers
32506     50/push-eax
32507     51/push-ecx
32508     # ecx = primitive
32509     8b/-> *(ebp+0x10) 1/r32/ecx
32510     # emit primitive name
32511     (emit-indent *(ebp+8) *Curr-block-depth)
32512     (lookup *(ecx+0x18) *(ecx+0x1c))  # Primitive-subx-name Primitive-subx-name => eax
32513     (write-buffered *(ebp+8) %eax)
32514     # emit rm32 if necessary
32515     (emit-subx-rm32 *(ebp+8) *(ecx+0x20) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # Primitive-subx-rm32
32516     # emit xm32 if necessary
32517     (emit-subx-rm32 *(ebp+8) *(ecx+0x34) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # Primitive-subx-xm32
32518     # emit r32 if necessary
32519     (emit-subx-r32 *(ebp+8) *(ecx+0x24) *(ebp+0xc))  # Primitive-subx-r32
32520     # emit x32 if necessary
32521     (emit-subx-x32 *(ebp+8) *(ecx+0x38) *(ebp+0xc))  # Primitive-subx-x32
32522     # emit imm32 if necessary
32523     (emit-subx-imm32 *(ebp+8) *(ecx+0x28) *(ebp+0xc))  # Primitive-subx-imm32
32524     # emit imm8 if necessary
32525     (emit-subx-imm8 *(ebp+8) *(ecx+0x2c) *(ebp+0xc))  # Primitive-subx-imm8
32526     # emit disp32 if necessary
32527     (emit-subx-disp32 *(ebp+8) *(ecx+0x30) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # Primitive-subx-disp32
32528     (write-buffered *(ebp+8) Newline)
32529 $emit-subx-primitive:end:
32530     # . restore registers
32531     59/pop-to-ecx
32532     58/pop-to-eax
32533     # . epilogue
32534     89/<- %esp 5/r32/ebp
32535     5d/pop-to-ebp
32536     c3/return
32537 
32538 emit-subx-rm32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
32539     # . prologue
32540     55/push-ebp
32541     89/<- %ebp 4/r32/esp
32542     # . save registers
32543     50/push-eax
32544     # if (l == 0) return
32545     81 7/subop/compare *(ebp+0xc) 0/imm32
32546     74/jump-if-= $emit-subx-rm32:end/disp8
32547     # var v/eax: (addr stmt-var)
32548     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # => eax
32549     (emit-subx-var-as-rm32 *(ebp+8) %eax)
32550 $emit-subx-rm32:end:
32551     # . restore registers
32552     58/pop-to-eax
32553     # . epilogue
32554     89/<- %esp 5/r32/ebp
32555     5d/pop-to-ebp
32556     c3/return
32557 
32558 get-stmt-operand-from-arg-location:  # stmt: (addr stmt), l: arg-location, err: (addr buffered-file), ed: (addr exit-descriptor) -> var/eax: (addr stmt-var)
32559     # . prologue
32560     55/push-ebp
32561     89/<- %ebp 4/r32/esp
32562     # . save registers
32563     51/push-ecx
32564     # eax = l
32565     8b/-> *(ebp+0xc) 0/r32/eax
32566     # ecx = stmt
32567     8b/-> *(ebp+8) 1/r32/ecx
32568     # if (l == 1) return stmt->inouts
32569     {
32570       3d/compare-eax-and 1/imm32
32571       75/jump-if-!= break/disp8
32572 $get-stmt-operand-from-arg-location:1:
32573       (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
32574       eb/jump $get-stmt-operand-from-arg-location:end/disp8
32575     }
32576     # if (l == 2) return stmt->inouts->next
32577     {
32578       3d/compare-eax-and 2/imm32
32579       75/jump-if-!= break/disp8
32580 $get-stmt-operand-from-arg-location:2:
32581       (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
32582       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
32583       eb/jump $get-stmt-operand-from-arg-location:end/disp8
32584     }
32585     # if (l == 3) return stmt->outputs
32586     {
32587       3d/compare-eax-and 3/imm32
32588       75/jump-if-!= break/disp8
32589 $get-stmt-operand-from-arg-location:3:
32590       (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
32591       eb/jump $get-stmt-operand-from-arg-location:end/disp8
32592     }
32593     # abort
32594     e9/jump $get-stmt-operand-from-arg-location:abort/disp32
32595 $get-stmt-operand-from-arg-location:end:
32596     # . restore registers
32597     59/pop-to-ecx
32598     # . epilogue
32599     89/<- %esp 5/r32/ebp
32600     5d/pop-to-ebp
32601     c3/return
32602 
32603 $get-stmt-operand-from-arg-location:abort:
32604     # error("invalid arg-location " eax)
32605     (write-buffered *(ebp+0x10) "invalid arg-location ")
32606     (write-int32-hex-buffered *(ebp+0x10) %eax)
32607     (write-buffered *(ebp+0x10) Newline)
32608     (flush *(ebp+0x10))
32609     (stop *(ebp+0x14) 1)
32610     # never gets here
32611 
32612 emit-subx-r32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
32613     # . prologue
32614     55/push-ebp
32615     89/<- %ebp 4/r32/esp
32616     # . save registers
32617     50/push-eax
32618     51/push-ecx
32619     # if (l == 0) return
32620     81 7/subop/compare *(ebp+0xc) 0/imm32
32621     0f 84/jump-if-= $emit-subx-r32:end/disp32
32622     # var v/eax: (addr stmt-var)
32623     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
32624     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
32625     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
32626 #?     (write-buffered Stderr "looking up ")
32627 #?     (write-buffered Stderr %eax)
32628 #?     (write-buffered Stderr Newline)
32629 #?     (flush Stderr)
32630     (maybe-get Mu-registers %eax 0xc)  # => eax: (addr register-index)
32631     (write-buffered *(ebp+8) Space)
32632     (write-int32-hex-buffered *(ebp+8) *eax)
32633     (write-buffered *(ebp+8) "/r32")
32634 $emit-subx-r32:end:
32635     # . restore registers
32636     59/pop-to-ecx
32637     58/pop-to-eax
32638     # . epilogue
32639     89/<- %esp 5/r32/ebp
32640     5d/pop-to-ebp
32641     c3/return
32642 
32643 emit-subx-x32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
32644     # . prologue
32645     55/push-ebp
32646     89/<- %ebp 4/r32/esp
32647     # . save registers
32648     50/push-eax
32649     51/push-ecx
32650     # if (l == 0) return
32651     81 7/subop/compare *(ebp+0xc) 0/imm32
32652     0f 84/jump-if-= $emit-subx-x32:end/disp32
32653     # var v/eax: (addr stmt-var)
32654     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
32655     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
32656     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
32657 #?     (write-buffered Stderr "looking up ")
32658 #?     (write-buffered Stderr %eax)
32659 #?     (write-buffered Stderr Newline)
32660 #?     (flush Stderr)
32661     (maybe-get Mu-registers %eax 0xc)  # => eax: (addr register-index)
32662     (write-buffered *(ebp+8) Space)
32663     (write-int32-hex-buffered *(ebp+8) *eax)
32664     (write-buffered *(ebp+8) "/x32")
32665 $emit-subx-x32:end:
32666     # . restore registers
32667     59/pop-to-ecx
32668     58/pop-to-eax
32669     # . epilogue
32670     89/<- %esp 5/r32/ebp
32671     5d/pop-to-ebp
32672     c3/return
32673 
32674 emit-subx-imm32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
32675     # . prologue
32676     55/push-ebp
32677     89/<- %ebp 4/r32/esp
32678     # . save registers
32679     50/push-eax
32680     51/push-ecx
32681     # if (l == 0) return
32682     81 7/subop/compare *(ebp+0xc) 0/imm32
32683     0f 84/jump-if-= $emit-subx-imm32:end/disp32
32684     # var v/eax: (handle var)
32685     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
32686     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
32687     (lookup *eax *(eax+4))  # Var-name Var-name => eax
32688     (write-buffered *(ebp+8) Space)
32689     (write-buffered *(ebp+8) %eax)
32690     (write-buffered *(ebp+8) "/imm32")
32691 $emit-subx-imm32:end:
32692     # . restore registers
32693     59/pop-to-ecx
32694     58/pop-to-eax
32695     # . epilogue
32696     89/<- %esp 5/r32/ebp
32697     5d/pop-to-ebp
32698     c3/return
32699 
32700 emit-subx-imm8:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
32701     # . prologue
32702     55/push-ebp
32703     89/<- %ebp 4/r32/esp
32704     # . save registers
32705     50/push-eax
32706     51/push-ecx
32707     # if (l == 0) return
32708     81 7/subop/compare *(ebp+0xc) 0/imm32
32709     0f 84/jump-if-= $emit-subx-imm32:end/disp32
32710     # var v/eax: (handle var)
32711     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
32712     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
32713     (lookup *eax *(eax+4))  # Var-name Var-name => eax
32714     (write-buffered *(ebp+8) Space)
32715     (write-buffered *(ebp+8) %eax)
32716     (write-buffered *(ebp+8) "/imm8")
32717 $emit-subx-imm8:end:
32718     # . restore registers
32719     59/pop-to-ecx
32720     58/pop-to-eax
32721     # . epilogue
32722     89/<- %esp 5/r32/ebp
32723     5d/pop-to-ebp
32724     c3/return
32725 
32726 emit-subx-disp32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
32727     # . prologue
32728     55/push-ebp
32729     89/<- %ebp 4/r32/esp
32730     # . save registers
32731     50/push-eax
32732     51/push-ecx
32733     # if (location == 0) return
32734     81 7/subop/compare *(ebp+0xc) 0/imm32
32735     0f 84/jump-if-= $emit-subx-disp32:end/disp32
32736     # var v/eax: (addr stmt-var)
32737     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # => eax
32738     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
32739     (lookup *eax *(eax+4))  # Var-name Var-name => eax
32740     (write-buffered *(ebp+8) Space)
32741     (write-buffered *(ebp+8) %eax)
32742     # hack: if instruction operation starts with "break", emit ":break"
32743     # var name/ecx: (addr array byte) = lookup(stmt->operation)
32744     8b/-> *(ebp+0x10) 0/r32/eax
32745     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
32746     89/<- %ecx 0/r32/eax
32747     {
32748       (string-starts-with? %ecx "break")  # => eax
32749       3d/compare-eax-and 0/imm32/false
32750       74/jump-if-= break/disp8
32751       (write-buffered *(ebp+8) ":break")
32752     }
32753     # hack: if instruction operation starts with "loop", emit ":loop"
32754     {
32755       (string-starts-with? %ecx "loop")  # => eax
32756       3d/compare-eax-and 0/imm32/false
32757       74/jump-if-= break/disp8
32758       (write-buffered *(ebp+8) ":loop")
32759     }
32760     (write-buffered *(ebp+8) "/disp32")
32761 $emit-subx-disp32:end:
32762     # . restore registers
32763     59/pop-to-ecx
32764     58/pop-to-eax
32765     # . epilogue
32766     89/<- %esp 5/r32/ebp
32767     5d/pop-to-ebp
32768     c3/return
32769 
32770 emit-call:  # out: (addr buffered-file), stmt: (addr stmt)
32771     # . prologue
32772     55/push-ebp
32773     89/<- %ebp 4/r32/esp
32774     # . save registers
32775     50/push-eax
32776     51/push-ecx
32777     #
32778     (emit-indent *(ebp+8) *Curr-block-depth)
32779     (write-buffered *(ebp+8) "(")
32780     # ecx = stmt
32781     8b/-> *(ebp+0xc) 1/r32/ecx
32782     # - emit function name
32783     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
32784     (write-buffered *(ebp+8) %eax)
32785     # - emit arguments
32786     # var curr/eax: (addr stmt-var) = lookup(stmt->inouts)
32787     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
32788     {
32789       # if (curr == null) break
32790       3d/compare-eax-and 0/imm32
32791       74/jump-if-= break/disp8
32792       #
32793       (emit-subx-call-operand *(ebp+8) %eax)
32794       # curr = lookup(curr->next)
32795       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
32796       eb/jump loop/disp8
32797     }
32798     #
32799     (write-buffered *(ebp+8) ")\n")
32800 $emit-call:end:
32801     # . restore registers
32802     59/pop-to-ecx
32803     58/pop-to-eax
32804     # . epilogue
32805     89/<- %esp 5/r32/ebp
32806     5d/pop-to-ebp
32807     c3/return
32808 
32809 emit-subx-call-operand:  # out: (addr buffered-file), s: (addr stmt-var)
32810     # shares code with emit-subx-var-as-rm32
32811     # . prologue
32812     55/push-ebp
32813     89/<- %ebp 4/r32/esp
32814     # . save registers
32815     50/push-eax
32816     51/push-ecx
32817     56/push-esi
32818     # ecx = s
32819     8b/-> *(ebp+0xc) 1/r32/ecx
32820     # var operand/esi: (addr var) = lookup(s->value)
32821     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
32822     89/<- %esi 0/r32/eax
32823     # if (operand->register && !s->is-deref?) emit "%__"
32824     {
32825 $emit-subx-call-operand:check-for-register-direct:
32826       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
32827       74/jump-if-= break/disp8
32828       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
32829       75/jump-if-!= break/disp8
32830 $emit-subx-call-operand:register-direct:
32831       (write-buffered *(ebp+8) " %")
32832       (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
32833       (write-buffered *(ebp+8) %eax)
32834       e9/jump $emit-subx-call-operand:end/disp32
32835     }
32836     # else if (operand->register && s->is-deref?) emit "*__"
32837     {
32838 $emit-subx-call-operand:check-for-register-indirect:
32839       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
32840       74/jump-if-= break/disp8
32841       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
32842       74/jump-if-= break/disp8
32843 $emit-subx-call-operand:register-indirect:
32844       (emit-subx-call-operand-register-indirect *(ebp+8) %esi)
32845       e9/jump $emit-subx-call-operand:end/disp32
32846     }
32847     # else if (operand->stack-offset) emit "*(ebp+__)"
32848     {
32849       81 7/subop/compare *(esi+0x14) 0/imm32  # Var-offset
32850       74/jump-if-= break/disp8
32851 $emit-subx-call-operand:stack:
32852       (emit-subx-call-operand-stack *(ebp+8) %esi)
32853       e9/jump $emit-subx-call-operand:end/disp32
32854     }
32855     # else if (operand->type == literal) emit "__"
32856     {
32857       (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
32858       81 7/subop/compare *(eax+4) 0/imm32  # Type-tree-value
32859       75/jump-if-!= break/disp8
32860 $emit-subx-call-operand:literal:
32861       (write-buffered *(ebp+8) Space)
32862       (lookup *esi *(esi+4))  # Var-name Var-name => eax
32863       (write-buffered *(ebp+8) %eax)
32864       e9/jump $emit-subx-call-operand:end/disp32
32865     }
32866     # else if (operand->type == literal-string) emit "__"
32867     {
32868       (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
32869       81 7/subop/compare *(eax+4) 0x10/imm32  # Type-tree-value
32870       75/jump-if-!= break/disp8
32871 $emit-subx-call-operand:literal-string:
32872       (write-buffered *(ebp+8) Space)
32873       (lookup *esi *(esi+4))  # Var-name Var-name => eax
32874       (write-buffered *(ebp+8) %eax)
32875     }
32876 $emit-subx-call-operand:end:
32877     # . restore registers
32878     5e/pop-to-esi
32879     59/pop-to-ecx
32880     58/pop-to-eax
32881     # . epilogue
32882     89/<- %esp 5/r32/ebp
32883     5d/pop-to-ebp
32884     c3/return
32885 
32886 emit-subx-call-operand-register-indirect:  # out: (addr buffered-file), v: (addr var)
32887     # . prologue
32888     55/push-ebp
32889     89/<- %ebp 4/r32/esp
32890     # . save registers
32891     50/push-eax
32892     51/push-ecx
32893     56/push-esi
32894     # esi = v
32895     8b/-> *(ebp+0xc) 6/r32/esi
32896     # var size/ecx: int = size-of-deref(v)
32897     (size-of-deref %esi)  # => eax
32898     89/<- %ecx 0/r32/eax
32899     # var reg-name/esi: (addr array byte) = lookup(v->register)
32900     (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
32901     89/<- %esi 0/r32/eax
32902     # TODO: assert size is a multiple of 4
32903     # var i/eax: int = 0
32904     b8/copy-to-eax 0/imm32
32905     {
32906 $emit-subx-call-operand-register-indirect:loop:
32907       # if (i >= size) break
32908       39/compare %eax 1/r32/ecx
32909       7d/jump-if->= break/disp8
32910       # emit " *(" v->register "+" i ")"
32911       (write-buffered *(ebp+8) " *(")
32912       (write-buffered *(ebp+8) %esi)
32913       (write-buffered *(ebp+8) "+")
32914       (write-int32-hex-buffered *(ebp+8) %eax)
32915       (write-buffered *(ebp+8) ")")
32916       # i += 4
32917       05/add-to-eax 4/imm32
32918       #
32919       eb/jump loop/disp8
32920     }
32921 $emit-subx-call-operand-register-indirect:end:
32922     # . restore registers
32923     5e/pop-to-esi
32924     59/pop-to-ecx
32925     58/pop-to-eax
32926     # . epilogue
32927     89/<- %esp 5/r32/ebp
32928     5d/pop-to-ebp
32929     c3/return
32930 
32931 emit-subx-call-operand-stack:  # out: (addr buffered-file), v: (addr var)
32932     # . prologue
32933     55/push-ebp
32934     89/<- %ebp 4/r32/esp
32935     # . save registers
32936     50/push-eax
32937     51/push-ecx
32938     56/push-esi
32939     # esi = v
32940     8b/-> *(ebp+0xc) 6/r32/esi
32941     # var curr/ecx: int = v->offset
32942     8b/-> *(esi+0x14) 1/r32/ecx  # Var-offset
32943     # var max/eax: int = v->offset + size-of(v)
32944     (size-of %esi)  # => eax
32945     # TODO: assert size is a multiple of 4
32946     01/add-to %eax 1/r32/ecx
32947     {
32948 $emit-subx-call-operand-stack:loop:
32949       # if (curr >= max) break
32950       39/compare %ecx 0/r32/eax
32951       7d/jump-if->= break/disp8
32952       # emit " *(ebp+" curr ")"
32953       (write-buffered *(ebp+8) " *(ebp+")
32954       (write-int32-hex-buffered *(ebp+8) %ecx)
32955       (write-buffered *(ebp+8) ")")
32956       # i += 4
32957       81 0/subop/add %ecx 4/imm32
32958       #
32959       eb/jump loop/disp8
32960     }
32961 $emit-subx-call-operand-stack:end:
32962     # . restore registers
32963     5e/pop-to-esi
32964     59/pop-to-ecx
32965     58/pop-to-eax
32966     # . epilogue
32967     89/<- %esp 5/r32/ebp
32968     5d/pop-to-ebp
32969     c3/return
32970 
32971 emit-subx-var-as-rm32:  # out: (addr buffered-file), s: (addr stmt-var)
32972     # . prologue
32973     55/push-ebp
32974     89/<- %ebp 4/r32/esp
32975     # . save registers
32976     50/push-eax
32977     51/push-ecx
32978     56/push-esi
32979     # ecx = s
32980     8b/-> *(ebp+0xc) 1/r32/ecx
32981     # var operand/esi: (addr var) = lookup(s->value)
32982     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
32983     89/<- %esi 0/r32/eax
32984     # if (operand->register && s->is-deref?) emit "*__"
32985     {
32986 $emit-subx-var-as-rm32:check-for-register-indirect:
32987       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
32988       74/jump-if-= break/disp8
32989       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
32990       74/jump-if-= break/disp8
32991 $emit-subx-var-as-rm32:register-indirect:
32992       (write-buffered *(ebp+8) " *")
32993       (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
32994       (write-buffered *(ebp+8) %eax)
32995       e9/jump $emit-subx-var-as-rm32:end/disp32
32996     }
32997     # if (operand->register && !s->is-deref?) emit "%__"
32998     {
32999 $emit-subx-var-as-rm32:check-for-register-direct:
33000       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
33001       74/jump-if-= break/disp8
33002       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
33003       75/jump-if-!= break/disp8
33004 $emit-subx-var-as-rm32:register-direct:
33005       (write-buffered *(ebp+8) " %")
33006       (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
33007       (write-buffered *(ebp+8) %eax)
33008       e9/jump $emit-subx-var-as-rm32:end/disp32
33009     }
33010     # else if (operand->stack-offset) emit "*(ebp+__)"
33011     {
33012       81 7/subop/compare *(esi+0x14) 0/imm32  # Var-offset
33013       74/jump-if-= break/disp8
33014 $emit-subx-var-as-rm32:stack:
33015       (write-buffered *(ebp+8) Space)
33016       (write-buffered *(ebp+8) "*(ebp+")
33017       (write-int32-hex-buffered *(ebp+8) *(esi+0x14))  # Var-offset
33018       (write-buffered *(ebp+8) ")")
33019     }
33020 $emit-subx-var-as-rm32:end:
33021     # . restore registers
33022     5e/pop-to-esi
33023     59/pop-to-ecx
33024     58/pop-to-eax
33025     # . epilogue
33026     89/<- %esp 5/r32/ebp
33027     5d/pop-to-ebp
33028     c3/return
33029 
33030 find-matching-primitive:  # primitives: (addr primitive), stmt: (addr stmt) -> result/eax: (addr primitive)
33031     # . prologue
33032     55/push-ebp
33033     89/<- %ebp 4/r32/esp
33034     # . save registers
33035     51/push-ecx
33036     # var curr/ecx: (addr primitive) = primitives
33037     8b/-> *(ebp+8) 1/r32/ecx
33038     {
33039 $find-matching-primitive:loop:
33040       # if (curr == null) break
33041       81 7/subop/compare %ecx 0/imm32
33042       74/jump-if-= break/disp8
33043       # if match(curr, stmt) return curr
33044       {
33045         (mu-stmt-matches-primitive? *(ebp+0xc) %ecx)  # => eax
33046         3d/compare-eax-and 0/imm32/false
33047         74/jump-if-= break/disp8
33048         89/<- %eax 1/r32/ecx
33049         eb/jump $find-matching-primitive:end/disp8
33050       }
33051 $find-matching-primitive:next-primitive:
33052       # curr = curr->next
33053       (lookup *(ecx+0x3c) *(ecx+0x40))  # Primitive-next Primitive-next => eax
33054       89/<- %ecx 0/r32/eax
33055       #
33056       e9/jump loop/disp32
33057     }
33058     # return null
33059     b8/copy-to-eax 0/imm32
33060 $find-matching-primitive:end:
33061     # . restore registers
33062     59/pop-to-ecx
33063     # . epilogue
33064     89/<- %esp 5/r32/ebp
33065     5d/pop-to-ebp
33066     c3/return
33067 
33068 mu-stmt-matches-primitive?:  # stmt: (addr stmt), primitive: (addr primitive) -> result/eax: boolean
33069     # A mu stmt matches a primitive if the name matches, all the inout vars
33070     # match, and all the output vars match.
33071     # Vars match if types match and registers match.
33072     # In addition, a stmt output matches a primitive's output if types match
33073     # and the primitive has a wildcard register.
33074     # . prologue
33075     55/push-ebp
33076     89/<- %ebp 4/r32/esp
33077     # . save registers
33078     51/push-ecx
33079     52/push-edx
33080     53/push-ebx
33081     56/push-esi
33082     57/push-edi
33083     # ecx = stmt
33084     8b/-> *(ebp+8) 1/r32/ecx
33085     # edx = primitive
33086     8b/-> *(ebp+0xc) 2/r32/edx
33087     {
33088 $mu-stmt-matches-primitive?:check-name:
33089       # if (primitive->name != stmt->operation) return false
33090       # . var esi: (addr array byte) = lookup(stmt->operation)
33091       (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
33092       89/<- %esi 0/r32/eax
33093       # . var edi: (addr array byte) = lookup(primitive->name)
33094       (lookup *edx *(edx+4))  # Primitive-name Primitive-name => eax
33095 #?       (write-buffered Stderr %eax)
33096 #?       (write-buffered Stderr Newline)
33097 #?       (flush Stderr)
33098       89/<- %edi 0/r32/eax
33099       (string-equal? %esi %edi)  # => eax
33100       3d/compare-eax-and 0/imm32/false
33101       75/jump-if-!= break/disp8
33102       b8/copy-to-eax 0/imm32
33103       e9/jump $mu-stmt-matches-primitive?:end/disp32
33104     }
33105     # var curr/esi: (addr stmt-var) = lookup(stmt->inouts)
33106     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
33107     89/<- %esi 0/r32/eax
33108     # var curr2/edi: (addr list var) = lookup(primitive->inouts)
33109     (lookup *(edx+8) *(edx+0xc))  # Primitive-inouts Primitive-inouts => eax
33110     89/<- %edi 0/r32/eax
33111     {
33112 $mu-stmt-matches-primitive?:inouts-loop:
33113       # if (curr == 0 && curr2 == 0) move on to check outputs
33114       {
33115 $mu-stmt-matches-primitive?:check-both-inouts-null:
33116         81 7/subop/compare %esi 0/imm32
33117         75/jump-if-!= break/disp8
33118 $mu-stmt-matches-primitive?:stmt-inout-null:
33119         81 7/subop/compare %edi 0/imm32
33120         0f 84/jump-if-= $mu-stmt-matches-primitive?:check-outputs/disp32
33121 $mu-stmt-matches-primitive?:stmt-inout-null-and-prim-inout-not-null:
33122         # return false
33123         b8/copy-to-eax 0/imm32/false
33124         e9/jump $mu-stmt-matches-primitive?:end/disp32
33125       }
33126       # if (curr2 == 0) return false
33127       {
33128 $mu-stmt-matches-primitive?:check-prim-inout-null:
33129         81 7/subop/compare %edi 0/imm32
33130         75/jump-if-!= break/disp8
33131 $mu-stmt-matches-primitive?:prim-inout-null:
33132         b8/copy-to-eax 0/imm32/false
33133         e9/jump $mu-stmt-matches-primitive?:end/disp32
33134       }
33135       # if (curr != curr2) return false
33136       {
33137 $mu-stmt-matches-primitive?:check-inouts-match:
33138         (lookup *edi *(edi+4))  # List-value List-value => eax
33139         (operand-matches-primitive? %esi %eax)  # => eax
33140         3d/compare-eax-and 0/imm32/false
33141         75/jump-if-!= break/disp8
33142 $mu-stmt-matches-primitive?:inouts-match:
33143         b8/copy-to-eax 0/imm32/false
33144         e9/jump $mu-stmt-matches-primitive?:end/disp32
33145       }
33146 $mu-stmt-matches-primitive?:next-inout:
33147       # curr = lookup(curr->next)
33148       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
33149       89/<- %esi 0/r32/eax
33150       # curr2 = lookup(curr2->next)
33151       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
33152       89/<- %edi 0/r32/eax
33153       #
33154       e9/jump loop/disp32
33155     }
33156 $mu-stmt-matches-primitive?:check-outputs:
33157     # var curr/esi: (addr stmt-var) = lookup(stmt->outputs)
33158     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
33159     89/<- %esi 0/r32/eax
33160     # var curr2/edi: (addr list var) = lookup(primitive->outputs)
33161     (lookup *(edx+0x10) *(edx+0x14))  # Primitive-outputs Primitive-outputs => eax
33162     89/<- %edi 0/r32/eax
33163     {
33164 $mu-stmt-matches-primitive?:outputs-loop:
33165       # if (curr == 0) return (curr2 == 0)
33166       {
33167 $mu-stmt-matches-primitive?:check-both-outputs-null:
33168         81 7/subop/compare %esi 0/imm32
33169         75/jump-if-!= break/disp8
33170         {
33171 $mu-stmt-matches-primitive?:stmt-output-null:
33172           81 7/subop/compare %edi 0/imm32
33173           75/jump-if-!= break/disp8
33174 $mu-stmt-matches-primitive?:both-outputs-null:
33175           # return true
33176           b8/copy-to-eax 1/imm32
33177           e9/jump $mu-stmt-matches-primitive?:end/disp32
33178         }
33179 $mu-stmt-matches-primitive?:stmt-output-null-and-prim-output-not-null:
33180         # return false
33181         b8/copy-to-eax 0/imm32
33182         e9/jump $mu-stmt-matches-primitive?:end/disp32
33183       }
33184       # if (curr2 == 0) return false
33185       {
33186 $mu-stmt-matches-primitive?:check-prim-output-null:
33187         81 7/subop/compare %edi 0/imm32
33188         75/jump-if-!= break/disp8
33189 $mu-stmt-matches-primitive?:prim-output-is-null:
33190         b8/copy-to-eax 0/imm32
33191         e9/jump $mu-stmt-matches-primitive?:end/disp32
33192       }
33193       # if (curr != curr2) return false
33194       {
33195 $mu-stmt-matches-primitive?:check-outputs-match:
33196         (lookup *edi *(edi+4))  # List-value List-value => eax
33197         (operand-matches-primitive? %esi %eax)  # => eax
33198         3d/compare-eax-and 0/imm32/false
33199         75/jump-if-!= break/disp8
33200 $mu-stmt-matches-primitive?:outputs-match:
33201         b8/copy-to-eax 0/imm32
33202         e9/jump $mu-stmt-matches-primitive?:end/disp32
33203       }
33204 $mu-stmt-matches-primitive?:next-output:
33205       # curr = lookup(curr->next)
33206       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
33207       89/<- %esi 0/r32/eax
33208       # curr2 = lookup(curr2->next)
33209       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
33210       89/<- %edi 0/r32/eax
33211       #
33212       e9/jump loop/disp32
33213     }
33214 $mu-stmt-matches-primitive?:return-true:
33215     b8/copy-to-eax 1/imm32
33216 $mu-stmt-matches-primitive?:end:
33217     # . restore registers
33218     5f/pop-to-edi
33219     5e/pop-to-esi
33220     5b/pop-to-ebx
33221     5a/pop-to-edx
33222     59/pop-to-ecx
33223     # . epilogue
33224     89/<- %esp 5/r32/ebp
33225     5d/pop-to-ebp
33226     c3/return
33227 
33228 operand-matches-primitive?:  # s: (addr stmt-var), prim-var: (addr var) -> result/eax: boolean
33229     # . prologue
33230     55/push-ebp
33231     89/<- %ebp 4/r32/esp
33232     # . save registers
33233     51/push-ecx
33234     52/push-edx
33235     53/push-ebx
33236     56/push-esi
33237     57/push-edi
33238     # ecx = s
33239     8b/-> *(ebp+8) 1/r32/ecx
33240     # var var/esi: (addr var) = lookup(s->value)
33241     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
33242     89/<- %esi 0/r32/eax
33243     # edi = prim-var
33244     8b/-> *(ebp+0xc) 7/r32/edi
33245 $operand-matches-primitive?:check-type:
33246     # if !category-match?(var->type, prim-var->type) return false
33247     # . var vtype/ebx: (addr type-tree) = lookup(var->type)
33248     (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
33249     89/<- %ebx 0/r32/eax
33250     # . if s is deref, vtype = vtype->right
33251     {
33252       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
33253       74/jump-if-= break/disp8
33254 $operand-matches-primitive?:is-deref:
33255       # . var t/eax: (addr type)
33256       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
33257       # . if !t->is-atom? t = t->left
33258       81 7/subop/compare *eax 0/imm32/false
33259       {
33260         75/jump-if-!= break/disp8
33261         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
33262       }
33263       # .
33264       89/<- %ebx 0/r32/eax
33265     }
33266     # . var ptype/eax: (addr type-tree) = lookup(prim-var->type)
33267     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
33268     (subx-type-category-match? %ebx %eax)  # => eax
33269     3d/compare-eax-and 0/imm32/false
33270     0f 84/jump-if-= $operand-matches-primitive?:return-false/disp32
33271     {
33272 $operand-matches-primitive?:check-register:
33273       # if prim-var is in memory and var is in register but dereference, match
33274       {
33275         81 7/subop/compare *(edi+0x18) 0/imm32  # Var-register
33276         0f 85/jump-if-!= break/disp32
33277         81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
33278         74/jump-if-= break/disp8
33279         81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
33280         74/jump-if-= break/disp8
33281 $operand-matches-primitive?:var-deref-match:
33282         e9/jump $operand-matches-primitive?:return-true/disp32
33283       }
33284       # if prim-var is in register and var is in register but dereference, no match
33285       {
33286         81 7/subop/compare *(edi+0x18) 0/imm32  # Var-register
33287         0f 84/jump-if-= break/disp32
33288         81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
33289         0f 84/jump-if-= break/disp32
33290         81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
33291         74/jump-if-= break/disp8
33292 $operand-matches-primitive?:var-deref-no-match:
33293         e9/jump $operand-matches-primitive?:return-false/disp32
33294       }
33295       # return false if var->register doesn't match prim-var->register
33296       {
33297         # if register addresses are equal, it's a match
33298         # var vreg/ebx: (addr array byte) = lookup(var->register)
33299         (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
33300         89/<- %ebx 0/r32/eax
33301         # var preg/ecx: (addr array byte) = lookup(prim-var->register)
33302         (lookup *(edi+0x18) *(edi+0x1c))  # Var-register Var-register => eax
33303         89/<- %ecx 0/r32/eax
33304         # if (vreg == preg) break
33305         39/compare %ecx 3/r32/ebx
33306         74/jump-if-= break/disp8
33307 $operand-matches-primitive?:var-register-no-match:
33308         # if either address is 0, return false
33309         81 7/subop/compare %ebx 0/imm32
33310         74/jump-if-=  $operand-matches-primitive?:return-false/disp8
33311         81 7/subop/compare %ecx 0/imm32
33312         74/jump-if-=  $operand-matches-primitive?:return-false/disp8
33313         # if prim-var->register is wildcard, it's a match
33314         (string-equal? %ecx "*")  # Any-register => eax
33315         3d/compare-eax-and 0/imm32/false
33316         75/jump-if-!= break/disp8
33317 $operand-matches-primitive?:wildcard-no-match:
33318         # if string contents aren't equal, return false
33319         (string-equal? %ecx %ebx)  # => eax
33320         3d/compare-eax-and 0/imm32/false
33321         74/jump-if-= $operand-matches-primitive?:return-false/disp8
33322       }
33323     }
33324 $operand-matches-primitive?:return-true:
33325     b8/copy-to-eax 1/imm32/true
33326     eb/jump $operand-matches-primitive?:end/disp8
33327 $operand-matches-primitive?:return-false:
33328     b8/copy-to-eax 0/imm32/false
33329 $operand-matches-primitive?:end:
33330     # . restore registers
33331     5f/pop-to-edi
33332     5e/pop-to-esi
33333     5b/pop-to-ebx
33334     5a/pop-to-edx
33335     59/pop-to-ecx
33336     # . epilogue
33337     89/<- %esp 5/r32/ebp
33338     5d/pop-to-ebp
33339     c3/return
33340 
33341 find-matching-function:  # functions: (addr function), stmt: (addr stmt) -> result/eax: (addr function)
33342     # . prologue
33343     55/push-ebp
33344     89/<- %ebp 4/r32/esp
33345     # . save registers
33346     51/push-ecx
33347     # var curr/ecx: (handle function) = functions
33348     8b/-> *(ebp+8) 1/r32/ecx
33349     {
33350       # if (curr == null) break
33351       81 7/subop/compare %ecx 0/imm32
33352       74/jump-if-= break/disp8
33353 #?       (write-buffered Stderr "iter\n")
33354 #?       (flush Stderr)
33355       # if match(stmt, curr) return curr
33356       {
33357         (mu-stmt-matches-function? *(ebp+0xc) %ecx)  # => eax
33358         3d/compare-eax-and 0/imm32/false
33359         74/jump-if-= break/disp8
33360         89/<- %eax 1/r32/ecx
33361         eb/jump $find-matching-function:end/disp8
33362       }
33363       # curr = curr->next
33364       (lookup *(ecx+0x20) *(ecx+0x24))  # Function-next Function-next => eax
33365       89/<- %ecx 0/r32/eax
33366       #
33367       eb/jump loop/disp8
33368     }
33369     # return null
33370     b8/copy-to-eax 0/imm32
33371 $find-matching-function:end:
33372     # . restore registers
33373     59/pop-to-ecx
33374     # . epilogue
33375     89/<- %esp 5/r32/ebp
33376     5d/pop-to-ebp
33377     c3/return
33378 
33379 # Just compare names; user-defined functions don't support overloading yet.
33380 mu-stmt-matches-function?:  # stmt: (addr stmt1), function: (addr function) -> result/eax: boolean
33381     # . prologue
33382     55/push-ebp
33383     89/<- %ebp 4/r32/esp
33384     # . save registers
33385     51/push-ecx
33386     # return function->name == stmt->operation
33387     # ecx = lookup(stmt->operation)
33388     8b/-> *(ebp+8) 0/r32/eax
33389     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
33390     89/<- %ecx 0/r32/eax
33391     # eax = lookup(function->name)
33392     8b/-> *(ebp+0xc) 0/r32/eax
33393     (lookup *eax *(eax+4))  # Function-name Function-name => eax
33394     (string-equal? %eax %ecx)  # => eax
33395 $mu-stmt-matches-function?:end:
33396     # . restore registers
33397     59/pop-to-ecx
33398     # . epilogue
33399     89/<- %esp 5/r32/ebp
33400     5d/pop-to-ebp
33401     c3/return
33402 
33403 # Type-checking happens elsewhere. This method is for selecting between
33404 # primitives.
33405 subx-type-category-match?:  # a: (addr type-tree), b: (addr type-tree) -> result/eax: boolean
33406     # . prologue
33407     55/push-ebp
33408     89/<- %ebp 4/r32/esp
33409     # . save registers
33410     51/push-ecx
33411     # var cata/ecx: int = type-category(a)
33412     (type-category *(ebp+8))  # => eax
33413     89/<- %ecx 0/r32/eax
33414     # var catb/eax: int = type-category(b)
33415     (type-category *(ebp+0xc))  # => eax
33416     # return cata == catb
33417     39/compare %eax 1/r32/ecx
33418     0f 94/set-byte-if-= %al
33419     81 4/subop/and %eax 0xff/imm32
33420 $subx-type-category-match?:end:
33421     # . restore registers
33422     59/pop-to-ecx
33423     # . epilogue
33424     89/<- %esp 5/r32/ebp
33425     5d/pop-to-ebp
33426     c3/return
33427 
33428 type-category:  # a: (addr type-tree) -> result/eax: int
33429     # . prologue
33430     55/push-ebp
33431     89/<- %ebp 4/r32/esp
33432     # . save registers
33433     51/push-ecx
33434     # var lit?/ecx: boolean = is-literal-type?(a)
33435     (is-simple-mu-type? *(ebp+8) 0)  # literal => eax
33436     89/<- %ecx 0/r32/eax
33437     # var float?/eax: int = is-float?(a)
33438     (is-simple-mu-type? *(ebp+8) 0xf)  # => eax
33439     # set bits for lit? and float?
33440     c1/shift 4/subop/left %ecx 1/imm8
33441     09/or %eax 1/r32/ecx
33442 $type-category:end:
33443     # . restore registers
33444     59/pop-to-ecx
33445     # . epilogue
33446     89/<- %esp 5/r32/ebp
33447     5d/pop-to-ebp
33448     c3/return
33449 
33450 is-simple-mu-type?:  # a: (addr type-tree), n: type-id -> result/eax: boolean
33451     # . prologue
33452     55/push-ebp
33453     89/<- %ebp 4/r32/esp
33454     # . save registers
33455     51/push-ecx
33456     # ecx = n
33457     8b/-> *(ebp+0xc) 1/r32/ecx
33458     # return (a->value == n)
33459     8b/-> *(ebp+8) 0/r32/eax
33460     39/compare *(eax+4) 1/r32/ecx  # Type-tree-value
33461     0f 94/set-byte-if-= %al
33462     81 4/subop/and %eax 0xff/imm32
33463 $is-simple-mu-type?:end:
33464     # . restore registers
33465     59/pop-to-ecx
33466     # . epilogue
33467     89/<- %esp 5/r32/ebp
33468     5d/pop-to-ebp
33469     c3/return
33470 
33471 is-mu-addr-type?:  # a: (addr type-tree) -> result/eax: boolean
33472     # . prologue
33473     55/push-ebp
33474     89/<- %ebp 4/r32/esp
33475     # eax = a
33476     8b/-> *(ebp+8) 0/r32/eax
33477     # if (!a->is-atom?) a = a->left
33478     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
33479     {
33480       75/jump-if-!= break/disp8
33481       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
33482     }
33483     # return (a->value == addr)
33484     81 7/subop/compare *(eax+4) 2/imm32/addr  # Type-tree-value
33485     0f 94/set-byte-if-= %al
33486     81 4/subop/and %eax 0xff/imm32
33487 $is-mu-addr-type?:end:
33488     # . epilogue
33489     89/<- %esp 5/r32/ebp
33490     5d/pop-to-ebp
33491     c3/return
33492 
33493 is-mu-array-type?:  # a: (addr type-tree) -> result/eax: boolean
33494     # . prologue
33495     55/push-ebp
33496     89/<- %ebp 4/r32/esp
33497     # eax = a
33498     8b/-> *(ebp+8) 0/r32/eax
33499     # if (!a->is-atom?) a = a->left
33500     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
33501     {
33502       75/jump-if-!= break/disp8
33503       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
33504     }
33505     # return (a->value == array)
33506     81 7/subop/compare *(eax+4) 3/imm32/array  # Type-tree-value
33507     0f 94/set-byte-if-= %al
33508     81 4/subop/and %eax 0xff/imm32
33509 $is-mu-array-type?:end:
33510     # . epilogue
33511     89/<- %esp 5/r32/ebp
33512     5d/pop-to-ebp
33513     c3/return
33514 
33515 is-mu-string-type?:  # a: (addr type-tree) -> result/eax: boolean
33516     # . prologue
33517     55/push-ebp
33518     89/<- %ebp 4/r32/esp
33519     # . save registers
33520     56/push-esi
33521     # esi = a
33522     8b/-> *(ebp+8) 6/r32/esi
33523     # if (a->is-atom?) return false
33524     81 7/subop/compare *esi 0/imm32/false  # Type-tree-is-atom
33525     0f 85/jump-if-!= $is-mu-string-type?:return-false/disp32
33526     # if a is not an addr, return false
33527     (is-mu-addr-type? %esi)  # => eax
33528     3d/compare-eax-with 0/imm32/false
33529     0f 84/jump-if-= $is-mu-string-type?:end/disp32  # eax changes var
33530     # if a is not an array, return false
33531     (lookup *(esi+0xc) *(esi+0x10))  # Type-tree-right Type-tree-right => eax
33532     (is-mu-array-type? %eax)  # => eax
33533     3d/compare-eax-with 0/imm32/false
33534     74/jump-if-= $is-mu-string-type?:end/disp8  # eax changes var
33535     # var p/eax: (addr type-tree) = payload of a
33536     (lookup *(esi+0xc) *(esi+0x10))  # Type-tree-right Type-tree-right => eax
33537     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
33538     # if p is an atom, return false
33539     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
33540     75/jump-if-!= $is-mu-string-type?:return-false/disp8
33541     # return (p == byte)
33542     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
33543     (is-simple-mu-type? %eax 8)  # byte => eax
33544     eb/jump $is-mu-string-type?:end/disp8
33545 $is-mu-string-type?:return-false:
33546     b8/copy-to-eax 0/imm32/false
33547 $is-mu-string-type?:end:
33548     # . restore registers
33549     5e/pop-to-esi
33550     # . epilogue
33551     89/<- %esp 5/r32/ebp
33552     5d/pop-to-ebp
33553     c3/return
33554 
33555 is-mu-stream-type?:  # a: (addr type-tree) -> result/eax: boolean
33556     # . prologue
33557     55/push-ebp
33558     89/<- %ebp 4/r32/esp
33559     # eax = a
33560     8b/-> *(ebp+8) 0/r32/eax
33561     # if (!a->is-atom?) a = a->left
33562     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
33563     {
33564       75/jump-if-!= break/disp8
33565       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
33566     }
33567     # return (a->value == stream)
33568     81 7/subop/compare *(eax+4) 0xb/imm32/stream  # Type-tree-value
33569     0f 94/set-byte-if-= %al
33570     81 4/subop/and %eax 0xff/imm32
33571 $is-mu-stream-type?:end:
33572     # . epilogue
33573     89/<- %esp 5/r32/ebp
33574     5d/pop-to-ebp
33575     c3/return
33576 
33577 test-emit-subx-stmt-primitive:
33578     # Primitive operation on a variable on the stack.
33579     #   increment foo
33580     # =>
33581     #   ff 0/subop/increment *(ebp-8)
33582     #
33583     # There's a variable on the var stack as follows:
33584     #   name: 'foo'
33585     #   type: int
33586     #   stack-offset: -8
33587     #
33588     # There's a primitive with this info:
33589     #   name: 'increment'
33590     #   inouts: int/mem
33591     #   value: 'ff 0/subop/increment'
33592     #
33593     # . prologue
33594     55/push-ebp
33595     89/<- %ebp 4/r32/esp
33596     # setup
33597     (clear-stream _test-output-stream)
33598     (clear-stream $_test-output-buffered-file->buffer)
33599     # simulate allocated payloads starting with an initial fake alloc-id (0x11)
33600 $test-emit-subx-stmt-primitive:initialize-type:
33601     # var type/ecx: (payload type-tree) = int
33602     68/push 0/imm32/right:null
33603     68/push 0/imm32/right:null
33604     68/push 0/imm32/left:unused
33605     68/push 1/imm32/value:int
33606     68/push 1/imm32/is-atom?:true
33607     68/push 0x11/imm32/alloc-id:fake:payload
33608     89/<- %ecx 4/r32/esp
33609 $test-emit-subx-stmt-primitive:initialize-var:
33610     # var var-foo/ecx: (payload var) = var(type)
33611     68/push 0/imm32/no-register
33612     68/push 0/imm32/no-register
33613     68/push -8/imm32/stack-offset
33614     68/push 1/imm32/block-depth
33615     51/push-ecx/type
33616     68/push 0x11/imm32/alloc-id:fake
33617     68/push 0/imm32/name
33618     68/push 0/imm32/name
33619     68/push 0x11/imm32/alloc-id:fake:payload
33620     89/<- %ecx 4/r32/esp
33621 $test-emit-subx-stmt-primitive:initialize-var-name:
33622     # var-foo->name = "foo"
33623     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
33624     (copy-array Heap "foo" %eax)
33625 $test-emit-subx-stmt-primitive:initialize-stmt-var:
33626     # var operand/ebx: (payload stmt-var) = stmt-var(var-foo)
33627     68/push 0/imm32/is-deref:false
33628     68/push 0/imm32/next
33629     68/push 0/imm32/next
33630     51/push-ecx/var-foo
33631     68/push 0x11/imm32/alloc-id:fake
33632     68/push 0x11/imm32/alloc-id:fake:payload
33633     89/<- %ebx 4/r32/esp
33634 $test-emit-subx-stmt-primitive:initialize-stmt:
33635     # var stmt/esi: (addr statement)
33636     68/push 0/imm32/no-outputs
33637     68/push 0/imm32/no-outputs
33638     53/push-ebx/inouts
33639     68/push 0x11/imm32/alloc-id:fake
33640     68/push 0/imm32/operation
33641     68/push 0/imm32/operation
33642     68/push 1/imm32/tag
33643     89/<- %esi 4/r32/esp
33644 $test-emit-subx-stmt-primitive:initialize-stmt-operation:
33645     # stmt->operation = "increment"
33646     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
33647     (copy-array Heap "increment" %eax)
33648 $test-emit-subx-stmt-primitive:initialize-primitive:
33649     # var primitives/ebx: (addr primitive)
33650     68/push 0/imm32/next
33651     68/push 0/imm32/next
33652     68/push 0/imm32/no-x32
33653     68/push 0/imm32/no-xm32
33654     68/push 0/imm32/no-disp32
33655     68/push 0/imm32/no-imm8
33656     68/push 0/imm32/no-imm32
33657     68/push 0/imm32/no-r32
33658     68/push 1/imm32/rm32-is-first-inout
33659     68/push 0/imm32/subx-name
33660     68/push 0/imm32/subx-name
33661     68/push 0/imm32/no-outputs
33662     68/push 0/imm32/no-outputs
33663     53/push-ebx/inouts  # hack: reuse stmt-var from call stmt as (list var) in function declaration
33664     68/push 0x11/imm32/alloc-id:fake
33665     68/push 0/imm32/name
33666     68/push 0/imm32/name
33667     89/<- %ebx 4/r32/esp
33668 $test-emit-subx-stmt-primitive:initialize-primitive-name:
33669     # primitives->name = "increment"
33670     (copy-array Heap "increment" %ebx)  # Primitive-name
33671 $test-emit-subx-stmt-primitive:initialize-primitive-subx-name:
33672     # primitives->subx-name = "ff 0/subop/increment"
33673     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
33674     (copy-array Heap "ff 0/subop/increment" %eax)
33675     # convert
33676     c7 0/subop/copy *Curr-block-depth 0/imm32
33677     (emit-subx-stmt _test-output-buffered-file %esi %ebx 0 Stderr 0)
33678     (flush _test-output-buffered-file)
33679 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
33685     # check output
33686     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment *(ebp+0xfffffff8)" "F - test-emit-subx-stmt-primitive")
33687     # . epilogue
33688     89/<- %esp 5/r32/ebp
33689     5d/pop-to-ebp
33690     c3/return
33691 
33692 test-emit-subx-stmt-primitive-register:
33693     # Primitive operation on a variable in a register.
33694     #   foo <- increment
33695     # =>
33696     #   ff 0/subop/increment %eax  # sub-optimal, but should suffice
33697     #
33698     # There's a variable on the var stack as follows:
33699     #   name: 'foo'
33700     #   type: int
33701     #   register: 'eax'
33702     #
33703     # There's a primitive with this info:
33704     #   name: 'increment'
33705     #   out: int/reg
33706     #   value: 'ff 0/subop/increment'
33707     #
33708     # . prologue
33709     55/push-ebp
33710     89/<- %ebp 4/r32/esp
33711     # setup
33712     (clear-stream _test-output-stream)
33713     (clear-stream $_test-output-buffered-file->buffer)
33714 $test-emit-subx-stmt-primitive-register:initialize-type:
33715     # var type/ecx: (payload type-tree) = int
33716     68/push 0/imm32/right:null
33717     68/push 0/imm32/right:null
33718     68/push 0/imm32/left:unused
33719     68/push 1/imm32/value:int
33720     68/push 1/imm32/is-atom?:true
33721     68/push 0x11/imm32/alloc-id:fake:payload
33722     89/<- %ecx 4/r32/esp
33723 $test-emit-subx-stmt-primitive-register:initialize-var:
33724     # var var-foo/ecx: (payload var)
33725     68/push 0/imm32/register
33726     68/push 0/imm32/register
33727     68/push 0/imm32/no-stack-offset
33728     68/push 1/imm32/block-depth
33729     51/push-ecx
33730     68/push 0x11/imm32/alloc-id:fake
33731     68/push 0/imm32/name
33732     68/push 0/imm32/name
33733     68/push 0x11/imm32/alloc-id:fake:payload
33734     89/<- %ecx 4/r32/esp
33735 $test-emit-subx-stmt-primitive-register:initialize-var-name:
33736     # var-foo->name = "foo"
33737     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
33738     (copy-array Heap "foo" %eax)
33739 $test-emit-subx-stmt-primitive-register:initialize-var-register:
33740     # var-foo->register = "eax"
33741     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
33742     (copy-array Heap "eax" %eax)
33743 $test-emit-subx-stmt-primitive-register:initialize-stmt-var:
33744     # var operand/ebx: (payload stmt-var)
33745     68/push 0/imm32/is-deref:false
33746     68/push 0/imm32/next
33747     68/push 0/imm32/next
33748     51/push-ecx/var-foo
33749     68/push 0x11/imm32/alloc-id:fake
33750     68/push 0x11/imm32/alloc-id:fake:payload
33751     89/<- %ebx 4/r32/esp
33752 $test-emit-subx-stmt-primitive-register:initialize-stmt:
33753     # var stmt/esi: (addr statement)
33754     53/push-ebx/outputs
33755     68/push 0x11/imm32/alloc-id:fake
33756     68/push 0/imm32/no-inouts
33757     68/push 0/imm32/no-inouts
33758     68/push 0/imm32/operation
33759     68/push 0/imm32/operation
33760     68/push 1/imm32
33761     89/<- %esi 4/r32/esp
33762 $test-emit-subx-stmt-primitive-register:initialize-stmt-operation:
33763     # stmt->operation = "increment"
33764     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
33765     (copy-array Heap "increment" %eax)
33766 $test-emit-subx-stmt-primitive-register:initialize-formal-var:
33767     # var formal-var/ebx: (payload var)
33768     68/push 0/imm32/register
33769     68/push 0/imm32/register
33770     68/push 0/imm32/no-stack-offset
33771     68/push 1/imm32/block-depth
33772     ff 6/subop/push *(ecx+0x10)  # Var-type + payload alloc id + handle alloc id
33773     68/push 0x11/imm32/alloc-id:fake
33774     68/push 0/imm32/name
33775     68/push 0/imm32/name
33776     68/push 0x11/imm32/alloc-id:fake:payload
33777     89/<- %ebx 4/r32/esp
33778 $test-emit-subx-stmt-primitive-register:initialize-formal-var-name:
33779     # formal-var->name = "dummy"
33780     8d/copy-address *(ebx+4) 0/r32/eax  # Var-name + 4
33781     (copy-array Heap "dummy" %eax)
33782 $test-emit-subx-stmt-primitive-register:initialize-formal-register:
33783     # formal-var->register = "*"
33784     8d/copy-address *(ebx+0x1c) 0/r32/eax  # Var-register + 4
33785     (copy-array Heap "*" %eax)  # Any-register
33786 $test-emit-subx-stmt-primitive-register:initialize-var-list:
33787     # var formal-outputs/ebx: (payload list var)
33788     68/push 0/imm32/next
33789     68/push 0/imm32/next
33790     53/push-ebx/formal-var
33791     68/push 0x11/imm32/alloc-id:fake
33792     68/push 0x11/imm32/alloc-id:fake:payload
33793     89/<- %ebx 4/r32/esp
33794 $test-emit-subx-stmt-primitive-register:initialize-primitive:
33795     # var primitives/ebx: (addr primitive)
33796     68/push 0/imm32/next
33797     68/push 0/imm32/next
33798     68/push 0/imm32/no-x32
33799     68/push 0/imm32/no-xm32
33800     68/push 0/imm32/no-disp32
33801     68/push 0/imm32/no-imm8
33802     68/push 0/imm32/no-imm32
33803     68/push 0/imm32/no-r32
33804     68/push 3/imm32/rm32-is-first-output
33805     68/push 0/imm32/subx-name
33806     68/push 0/imm32/subx-name
33807     53/push-ebx/outputs
33808     68/push 0x11/imm32/alloc-id:fake
33809     68/push 0/imm32/no-inouts
33810     68/push 0/imm32/no-inouts
33811     68/push 0/imm32/name
33812     68/push 0/imm32/name
33813     89/<- %ebx 4/r32/esp
33814 $test-emit-subx-stmt-primitive-register:initialize-primitive-name:
33815     # primitives->name = "increment"
33816     (copy-array Heap "increment" %ebx)  # Primitive-name
33817 $test-emit-subx-stmt-primitive-register:initialize-primitive-subx-name:
33818     # primitives->subx-name = "ff 0/subop/increment"
33819     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
33820     (copy-array Heap "ff 0/subop/increment" %eax)
33821     # convert
33822     c7 0/subop/copy *Curr-block-depth 0/imm32
33823     (emit-subx-stmt _test-output-buffered-file %esi %ebx 0 Stderr 0)
33824     (flush _test-output-buffered-file)
33825 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
33831     # check output
33832     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-primitive-register")
33833     # . epilogue
33834     89/<- %esp 5/r32/ebp
33835     5d/pop-to-ebp
33836     c3/return
33837 
33838 test-emit-subx-stmt-select-primitive:
33839     # Select the right primitive between overloads.
33840     #   foo <- increment
33841     # =>
33842     #   ff 0/subop/increment %eax  # sub-optimal, but should suffice
33843     #
33844     # There's a variable on the var stack as follows:
33845     #   name: 'foo'
33846     #   type: int
33847     #   register: 'eax'
33848     #
33849     # There's two primitives, as follows:
33850     #   - name: 'increment'
33851     #     out: int/reg
33852     #     value: 'ff 0/subop/increment'
33853     #   - name: 'increment'
33854     #     inout: int/mem
33855     #     value: 'ff 0/subop/increment'
33856     #
33857     # . prologue
33858     55/push-ebp
33859     89/<- %ebp 4/r32/esp
33860     # setup
33861     (clear-stream _test-output-stream)
33862     (clear-stream $_test-output-buffered-file->buffer)
33863 $test-emit-subx-stmt-select-primitive:initialize-type:
33864     # var type/ecx: (payload type-tree) = int
33865     68/push 0/imm32/right:null
33866     68/push 0/imm32/right:null
33867     68/push 0/imm32/left:unused
33868     68/push 1/imm32/value:int
33869     68/push 1/imm32/is-atom?:true
33870     68/push 0x11/imm32/alloc-id:fake:payload
33871     89/<- %ecx 4/r32/esp
33872 $test-emit-subx-stmt-select-primitive:initialize-var:
33873     # var var-foo/ecx: (payload var)
33874     68/push 0/imm32/register
33875     68/push 0/imm32/register
33876     68/push 0/imm32/no-stack-offset
33877     68/push 1/imm32/block-depth
33878     51/push-ecx
33879     68/push 0x11/imm32/alloc-id:fake
33880     68/push 0/imm32/name
33881     68/push 0/imm32/name
33882     68/push 0x11/imm32/alloc-id:fake:payload
33883     89/<- %ecx 4/r32/esp
33884 $test-emit-subx-stmt-select-primitive:initialize-var-name:
33885     # var-foo->name = "foo"
33886     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
33887     (copy-array Heap "foo" %eax)
33888 $test-emit-subx-stmt-select-primitive:initialize-var-register:
33889     # var-foo->register = "eax"
33890     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
33891     (copy-array Heap "eax" %eax)
33892 $test-emit-subx-stmt-select-primitive:initialize-stmt-var:
33893     # var operand/ebx: (payload stmt-var)
33894     68/push 0/imm32/is-deref:false
33895     68/push 0/imm32/next
33896     68/push 0/imm32/next
33897     51/push-ecx/var-foo
33898     68/push 0x11/imm32/alloc-id:fake
33899     68/push 0x11/imm32/alloc-id:fake:payload
33900     89/<- %ebx 4/r32/esp
33901 $test-emit-subx-stmt-select-primitive:initialize-stmt:
33902     # var stmt/esi: (addr statement)
33903     53/push-ebx/outputs
33904     68/push 0x11/imm32/alloc-id:fake
33905     68/push 0/imm32/no-inouts
33906     68/push 0/imm32/no-inouts
33907     68/push 0/imm32/operation
33908     68/push 0/imm32/operation
33909     68/push 1/imm32
33910     89/<- %esi 4/r32/esp
33911 $test-emit-subx-stmt-select-primitive:initialize-stmt-operation:
33912     # stmt->operation = "increment"
33913     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
33914     (copy-array Heap "increment" %eax)
33915 $test-emit-subx-stmt-select-primitive:initialize-formal-var:
33916     # var formal-var/ebx: (payload var)
33917     68/push 0/imm32/register
33918     68/push 0/imm32/register
33919     68/push 0/imm32/no-stack-offset
33920     68/push 1/imm32/block-depth
33921     ff 6/subop/push *(ecx+0x10)  # Var-type + payload alloc id + handle alloc id
33922     68/push 0x11/imm32/alloc-id:fake
33923     68/push 0/imm32/name
33924     68/push 0/imm32/name
33925     68/push 0x11/imm32/alloc-id:fake:payload
33926     89/<- %ebx 4/r32/esp
33927 $test-emit-subx-stmt-select-primitive:initialize-formal-var-name:
33928     # formal-var->name = "dummy"
33929     8d/copy-address *(ebx+4) 0/r32/eax  # Var-name + 4
33930     (copy-array Heap "dummy" %eax)
33931 $test-emit-subx-stmt-select-primitive:initialize-formal-register:
33932     # formal-var->register = "*"
33933     8d/copy-address *(ebx+0x1c) 0/r32/eax  # Var-register + 4
33934     (copy-array Heap "*" %eax)  # Any-register
33935 $test-emit-subx-stmt-select-primitive:initialize-var-list:
33936     # var formal-outputs/ebx: (payload list var)
33937     68/push 0/imm32/next
33938     68/push 0/imm32/next
33939     53/push-ebx/formal-var
33940     68/push 0x11/imm32/alloc-id:fake
33941     68/push 0x11/imm32/alloc-id:fake:payload
33942     89/<- %ebx 4/r32/esp
33943 $test-emit-subx-stmt-select-primitive:initialize-primitive2:
33944     # var primitive2/edi: (payload primitive)
33945     68/push 0/imm32/next
33946     68/push 0/imm32/next
33947     68/push 0/imm32/no-x32
33948     68/push 0/imm32/no-xm32
33949     68/push 0/imm32/no-disp32
33950     68/push 0/imm32/no-imm8
33951     68/push 0/imm32/no-imm32
33952     68/push 0/imm32/no-r32
33953     68/push 3/imm32/rm32-is-first-output
33954     68/push 0/imm32/subx-name
33955     68/push 0/imm32/subx-name
33956     53/push-ebx/outputs
33957     68/push 0x11/imm32/alloc-id:fake
33958     68/push 0/imm32/no-inouts
33959     68/push 0/imm32/no-inouts
33960     68/push 0/imm32/name
33961     68/push 0/imm32/name
33962     68/push 0x11/imm32/alloc-id:fake:payload
33963     89/<- %edi 4/r32/esp
33964 $test-emit-subx-stmt-select-primitive:initialize-primitive2-name:
33965     # primitives->name = "increment"
33966     8d/copy-address *(edi+4) 0/r32/eax  # Primitive-name + 4
33967     (copy-array Heap "increment" %eax)
33968 $test-emit-subx-stmt-select-primitive:initialize-primitive2-subx-name:
33969     # primitives->subx-name = "ff 0/subop/increment"
33970     8d/copy-address *(edi+0x1c) 0/r32/eax  # Primitive-subx-name + 4
33971     (copy-array Heap "ff 0/subop/increment" %eax)
33972 $test-emit-subx-stmt-select-primitive:initialize-primitive:
33973     # var primitives/ebx: (addr primitive)
33974     57/push-edi
33975     68/push 0x11/imm32/alloc-id:fake
33976     68/push 0/imm32/no-x32
33977     68/push 0/imm32/no-xm32
33978     68/push 0/imm32/no-disp32
33979     68/push 0/imm32/no-imm8
33980     68/push 0/imm32/no-imm32
33981     68/push 0/imm32/no-r32
33982     68/push 1/imm32/rm32-is-first-inout
33983     68/push 0/imm32/subx-name
33984     68/push 0/imm32/subx-name
33985     68/push 0/imm32/no-outputs
33986     68/push 0/imm32/no-outputs
33987     53/push-ebx/inouts  # hack: reuse stmt-var from call stmt as (list var) in function declaration
33988     68/push 0x11/imm32/alloc-id:fake
33989     68/push 0/imm32/name
33990     68/push 0/imm32/name
33991     89/<- %ebx 4/r32/esp
33992 $test-emit-subx-stmt-select-primitive:initialize-primitive-name:
33993     # primitives->name = "increment"
33994     (copy-array Heap "increment" %ebx)  # Primitive-name
33995 $test-emit-subx-stmt-select-primitive:initialize-primitive-subx-name:
33996     # primitives->subx-name = "ff 0/subop/increment"
33997     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
33998     (copy-array Heap "ff 0/subop/increment" %eax)
33999     # convert
34000     c7 0/subop/copy *Curr-block-depth 0/imm32
34001     (emit-subx-stmt _test-output-buffered-file %esi %ebx 0 Stderr 0)
34002     (flush _test-output-buffered-file)
34003 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
34009     # check output
34010     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-select-primitive")
34011     # . epilogue
34012     89/<- %esp 5/r32/ebp
34013     5d/pop-to-ebp
34014     c3/return
34015 
34016 test-emit-subx-stmt-select-primitive-2:
34017     # Select the right primitive between overloads.
34018     #   increment foo
34019     # =>
34020     #   ff 0/subop/increment %eax  # sub-optimal, but should suffice
34021     #
34022     # There's a variable on the var stack as follows:
34023     #   name: 'foo'
34024     #   type: int
34025     #   register: 'eax'
34026     #
34027     # There's two primitives, as follows:
34028     #   - name: 'increment'
34029     #     out: int/reg
34030     #     value: 'ff 0/subop/increment'
34031     #   - name: 'increment'
34032     #     inout: int/mem
34033     #     value: 'ff 0/subop/increment'
34034     #
34035     # . prologue
34036     55/push-ebp
34037     89/<- %ebp 4/r32/esp
34038     # setup
34039     (clear-stream _test-output-stream)
34040     (clear-stream $_test-output-buffered-file->buffer)
34041 $test-emit-subx-stmt-select-primitive-2:initialize-type:
34042     # var type/ecx: (payload type-tree) = int
34043     68/push 0/imm32/right:null
34044     68/push 0/imm32/right:null
34045     68/push 0/imm32/left:unused
34046     68/push 1/imm32/value:int
34047     68/push 1/imm32/is-atom?:true
34048     68/push 0x11/imm32/alloc-id:fake:payload
34049     89/<- %ecx 4/r32/esp
34050 $test-emit-subx-stmt-select-primitive-2:initialize-var:
34051     # var var-foo/ecx: (payload var)
34052     68/push 0/imm32/register
34053     68/push 0/imm32/register
34054     68/push 0/imm32/no-stack-offset
34055     68/push 1/imm32/block-depth
34056     51/push-ecx
34057     68/push 0x11/imm32/alloc-id:fake
34058     68/push 0/imm32/name
34059     68/push 0/imm32/name
34060     68/push 0x11/imm32/alloc-id:fake:payload
34061     89/<- %ecx 4/r32/esp
34062 $test-emit-subx-stmt-select-primitive-2:initialize-var-name:
34063     # var-foo->name = "foo"
34064     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
34065     (copy-array Heap "foo" %eax)
34066 $test-emit-subx-stmt-select-primitive-2:initialize-var-register:
34067     # var-foo->register = "eax"
34068     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
34069     (copy-array Heap "eax" %eax)
34070 $test-emit-subx-stmt-select-primitive-2:initialize-stmt-var:
34071     # var operand/ebx: (payload stmt-var)
34072     68/push 0/imm32/is-deref:false
34073     68/push 0/imm32/next
34074     68/push 0/imm32/next
34075     51/push-ecx/var-foo
34076     68/push 0x11/imm32/alloc-id:fake
34077     68/push 0x11/imm32/alloc-id:fake:payload
34078     89/<- %ebx 4/r32/esp
34079 $test-emit-subx-stmt-select-primitive-2:initialize-stmt:
34080     # var stmt/esi: (addr statement)
34081     68/push 0/imm32/no-outputs
34082     68/push 0/imm32/no-outputs
34083     53/push-ebx/inouts
34084     68/push 0x11/imm32/alloc-id:fake
34085     68/push 0/imm32/operation
34086     68/push 0/imm32/operation
34087     68/push 1/imm32
34088     89/<- %esi 4/r32/esp
34089 $test-emit-subx-stmt-select-primitive-2:initialize-stmt-operation:
34090     # stmt->operation = "increment"
34091     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
34092     (copy-array Heap "increment" %eax)
34093 $test-emit-subx-stmt-select-primitive-2:initialize-formal-var:
34094     # var formal-var/ebx: (payload var)
34095     68/push 0/imm32/register
34096     68/push 0/imm32/register
34097     68/push 0/imm32/no-stack-offset
34098     68/push 1/imm32/block-depth
34099     ff 6/subop/push *(ecx+0x10)  # Var-type + payload alloc id + handle alloc id
34100     68/push 0x11/imm32/alloc-id:fake
34101     68/push 0/imm32/name
34102     68/push 0/imm32/name
34103     68/push 0x11/imm32/alloc-id:fake:payload
34104     89/<- %ebx 4/r32/esp
34105 $test-emit-subx-stmt-select-primitive-2:initialize-formal-var-name:
34106     # formal-var->name = "dummy"
34107     8d/copy-address *(ebx+4) 0/r32/eax  # Var-name + 4
34108     (copy-array Heap "dummy" %eax)
34109 $test-emit-subx-stmt-select-primitive-2:initialize-formal-register:
34110     # formal-var->register = "*"
34111     8d/copy-address *(ebx+0x1c) 0/r32/eax  # Var-register + 4
34112     (copy-array Heap "*" %eax)  # Any-register
34113 $test-emit-subx-stmt-select-primitive-2:initialize-var-list:
34114     # var formal-outputs/ebx: (payload list stmt-var)
34115     68/push 0/imm32/next
34116     68/push 0/imm32/next
34117     53/push-ebx/formal-var
34118     68/push 0x11/imm32/alloc-id:fake
34119     68/push 0x11/imm32/alloc-id:fake:payload
34120     89/<- %ebx 4/r32/esp
34121 $test-emit-subx-stmt-select-primitive-2:initialize-primitive2:
34122     # var primitive2/edi: (payload primitive)
34123     68/push 0/imm32/next
34124     68/push 0/imm32/next
34125     68/push 0/imm32/no-x32
34126     68/push 0/imm32/no-xm32
34127     68/push 0/imm32/no-disp32
34128     68/push 0/imm32/no-imm8
34129     68/push 0/imm32/no-imm32
34130     68/push 0/imm32/no-r32
34131     68/push 3/imm32/rm32-is-first-output
34132     68/push 0/imm32/subx-name
34133     68/push 0/imm32/subx-name
34134     53/push-ebx/outputs
34135     68/push 0x11/imm32/alloc-id:fake
34136     68/push 0/imm32/no-inouts
34137     68/push 0/imm32/no-inouts
34138     68/push 0/imm32/name
34139     68/push 0/imm32/name
34140     68/push 0x11/imm32/alloc-id:fake:payload
34141     89/<- %edi 4/r32/esp
34142 $test-emit-subx-stmt-select-primitive-2:initialize-primitive2-name:
34143     # primitives->name = "increment"
34144     8d/copy-address *(edi+4) 0/r32/eax  # Primitive-name + 4
34145     (copy-array Heap "increment" %eax)
34146 $test-emit-subx-stmt-select-primitive-2:initialize-primitive2-subx-name:
34147     # primitives->subx-name = "ff 0/subop/increment"
34148     8d/copy-address *(edi+0x1c) 0/r32/eax  # Primitive-subx-name + 4
34149     (copy-array Heap "ff 0/subop/increment" %eax)
34150 $test-emit-subx-stmt-select-primitive-2:initialize-primitive:
34151     # var primitives/ebx: (addr primitive)
34152     57/push-edi
34153     68/push 0x11/imm32/alloc-id:fake
34154     68/push 0/imm32/no-x32
34155     68/push 0/imm32/no-xm32
34156     68/push 0/imm32/no-disp32
34157     68/push 0/imm32/no-imm8
34158     68/push 0/imm32/no-imm32
34159     68/push 0/imm32/no-r32
34160     68/push 1/imm32/rm32-is-first-inout
34161     68/push 0/imm32/subx-name
34162     68/push 0/imm32/subx-name
34163     68/push 0/imm32/no-outputs
34164     68/push 0/imm32/no-outputs
34165     53/push-ebx/inouts  # hack: reuse stmt-var from call stmt as (list var) in function declaration
34166     68/push 0x11/imm32/alloc-id:fake
34167     68/push 0/imm32/name
34168     68/push 0/imm32/name
34169     89/<- %ebx 4/r32/esp
34170 $test-emit-subx-stmt-select-primitive-2:initialize-primitive-name:
34171     # primitives->name = "increment"
34172     (copy-array Heap "increment" %ebx)  # Primitive-name
34173 $test-emit-subx-stmt-select-primitive-2:initialize-primitive-subx-name:
34174     # primitives->subx-name = "ff 0/subop/increment"
34175     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
34176     (copy-array Heap "ff 0/subop/increment" %eax)
34177     # convert
34178     c7 0/subop/copy *Curr-block-depth 0/imm32
34179     (emit-subx-stmt _test-output-buffered-file %esi %ebx 0 Stderr 0)
34180     (flush _test-output-buffered-file)
34181 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
34187     # check output
34188     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-select-primitive-2")
34189     # . epilogue
34190     89/<- %esp 5/r32/ebp
34191     5d/pop-to-ebp
34192     c3/return
34193 
34194 test-increment-register:
34195     # Select the right register between overloads.
34196     #   foo <- increment
34197     # =>
34198     #   50/increment-eax
34199     #
34200     # There's a variable on the var stack as follows:
34201     #   name: 'foo'
34202     #   type: int
34203     #   register: 'eax'
34204     #
34205     # Primitives are the global definitions.
34206     #
34207     # . prologue
34208     55/push-ebp
34209     89/<- %ebp 4/r32/esp
34210     # setup
34211     (clear-stream _test-output-stream)
34212     (clear-stream $_test-output-buffered-file->buffer)
34213 $test-increment-register:initialize-type:
34214     # var type/ecx: (payload type-tree) = int
34215     68/push 0/imm32/right:null
34216     68/push 0/imm32/right:null
34217     68/push 0/imm32/left:unused
34218     68/push 1/imm32/value:int
34219     68/push 1/imm32/is-atom?:true
34220     68/push 0x11/imm32/alloc-id:fake:payload
34221     89/<- %ecx 4/r32/esp
34222 $test-increment-register:initialize-var:
34223     # var var-foo/ecx: (payload var)
34224     68/push 0/imm32/register
34225     68/push 0/imm32/register
34226     68/push 0/imm32/no-stack-offset
34227     68/push 1/imm32/block-depth
34228     51/push-ecx
34229     68/push 0x11/imm32/alloc-id:fake
34230     68/push 0/imm32/name
34231     68/push 0/imm32/name
34232     68/push 0x11/imm32/alloc-id:fake:payload
34233     89/<- %ecx 4/r32/esp
34234 $test-increment-register:initialize-var-name:
34235     # var-foo->name = "foo"
34236     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
34237     (copy-array Heap "foo" %eax)
34238 $test-increment-register:initialize-var-register:
34239     # var-foo->register = "eax"
34240     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
34241     (copy-array Heap "eax" %eax)
34242 $test-increment-register:initialize-stmt-var:
34243     # var operand/ebx: (payload stmt-var)
34244     68/push 0/imm32/is-deref:false
34245     68/push 0/imm32/next
34246     68/push 0/imm32/next
34247     51/push-ecx/var-foo
34248     68/push 0x11/imm32/alloc-id:fake
34249     68/push 0x11/imm32/alloc-id:fake:payload
34250     89/<- %ebx 4/r32/esp
34251 $test-increment-register:initialize-stmt:
34252     # var stmt/esi: (addr statement)
34253     53/push-ebx/outputs
34254     68/push 0x11/imm32/alloc-id:fake
34255     68/push 0/imm32/no-inouts
34256     68/push 0/imm32/no-inouts
34257     68/push 0/imm32/operation
34258     68/push 0/imm32/operation
34259     68/push 1/imm32
34260     89/<- %esi 4/r32/esp
34261 $test-increment-register:initialize-stmt-operation:
34262     # stmt->operation = "increment"
34263     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
34264     (copy-array Heap "increment" %eax)
34265     # convert
34266     c7 0/subop/copy *Curr-block-depth 0/imm32
34267     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
34268     (flush _test-output-buffered-file)
34269 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
34275     # check output
34276     (check-next-stream-line-equal _test-output-stream "40/increment-eax" "F - test-increment-register")
34277     # . epilogue
34278     89/<- %esp 5/r32/ebp
34279     5d/pop-to-ebp
34280     c3/return
34281 
34282 test-add-reg-to-reg:
34283     #   var1/reg <- add var2/reg
34284     # =>
34285     #   01/add-to %var1 var2
34286     #
34287     # . prologue
34288     55/push-ebp
34289     89/<- %ebp 4/r32/esp
34290     # setup
34291     (clear-stream _test-output-stream)
34292     (clear-stream $_test-output-buffered-file->buffer)
34293 $test-add-reg-to-reg:initialize-type:
34294     # var type/ecx: (payload type-tree) = int
34295     68/push 0/imm32/right:null
34296     68/push 0/imm32/right:null
34297     68/push 0/imm32/left:unused
34298     68/push 1/imm32/value:int
34299     68/push 1/imm32/is-atom?:true
34300     68/push 0x11/imm32/alloc-id:fake:payload
34301     89/<- %ecx 4/r32/esp
34302 $test-add-reg-to-reg:initialize-var1:
34303     # var var1/ecx: (payload var)
34304     68/push 0/imm32/register
34305     68/push 0/imm32/register
34306     68/push 0/imm32/no-stack-offset
34307     68/push 1/imm32/block-depth
34308     51/push-ecx
34309     68/push 0x11/imm32/alloc-id:fake
34310     68/push 0/imm32/name
34311     68/push 0/imm32/name
34312     68/push 0x11/imm32/alloc-id:fake:payload
34313     89/<- %ecx 4/r32/esp
34314 $test-add-reg-to-reg:initialize-var1-name:
34315     # var1->name = "var1"
34316     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
34317     (copy-array Heap "var1" %eax)
34318 $test-add-reg-to-reg:initialize-var1-register:
34319     # var1->register = "eax"
34320     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
34321     (copy-array Heap "eax" %eax)
34322 $test-add-reg-to-reg:initialize-var2:
34323     # var var2/edx: (payload var)
34324     68/push 0/imm32/register
34325     68/push 0/imm32/register
34326     68/push 0/imm32/no-stack-offset
34327     68/push 1/imm32/block-depth
34328     ff 6/subop/push *(ecx+0x10)
34329     68/push 0x11/imm32/alloc-id:fake
34330     68/push 0/imm32/name
34331     68/push 0/imm32/name
34332     68/push 0x11/imm32/alloc-id:fake:payload
34333     89/<- %edx 4/r32/esp
34334 $test-add-reg-to-reg:initialize-var2-name:
34335     # var2->name = "var2"
34336     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
34337     (copy-array Heap "var2" %eax)
34338 $test-add-reg-to-reg:initialize-var2-register:
34339     # var2->register = "ecx"
34340     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
34341     (copy-array Heap "ecx" %eax)
34342 $test-add-reg-to-reg:initialize-inouts:
34343     # var inouts/esi: (payload stmt-var) = [var2]
34344     68/push 0/imm32/is-deref:false
34345     68/push 0/imm32/next
34346     68/push 0/imm32/next
34347     52/push-edx/var2
34348     68/push 0x11/imm32/alloc-id:fake
34349     68/push 0x11/imm32/alloc-id:fake:payload
34350     89/<- %esi 4/r32/esp
34351 $test-add-reg-to-reg:initialize-outputs:
34352     # var outputs/edi: (payload stmt-var) = [var1]
34353     68/push 0/imm32/is-deref:false
34354     68/push 0/imm32/next
34355     68/push 0/imm32/next
34356     51/push-ecx/var1
34357     68/push 0x11/imm32/alloc-id:fake
34358     68/push 0x11/imm32/alloc-id:fake:payload
34359     89/<- %edi 4/r32/esp
34360 $test-add-reg-to-reg:initialize-stmt:
34361     # var stmt/esi: (addr statement)
34362     68/push 0/imm32/next
34363     68/push 0/imm32/next
34364     57/push-edi/outputs
34365     68/push 0x11/imm32/alloc-id:fake
34366     56/push-esi/inouts
34367     68/push 0x11/imm32/alloc-id:fake
34368     68/push 0/imm32/operation
34369     68/push 0/imm32/operation
34370     68/push 1/imm32/tag:stmt1
34371     89/<- %esi 4/r32/esp
34372 $test-add-reg-to-reg:initialize-stmt-operation:
34373     # stmt->operation = "add"
34374     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
34375     (copy-array Heap "add" %eax)
34376     # convert
34377     c7 0/subop/copy *Curr-block-depth 0/imm32
34378     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
34379     (flush _test-output-buffered-file)
34380 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
34386     # check output
34387     (check-next-stream-line-equal _test-output-stream "01/add-to %eax 0x00000001/r32" "F - test-add-reg-to-reg")
34388     # . epilogue
34389     89/<- %esp 5/r32/ebp
34390     5d/pop-to-ebp
34391     c3/return
34392 
34393 test-add-reg-to-mem:
34394     #   add-to var1 var2/reg
34395     # =>
34396     #   01/add-to *(ebp+__) var2
34397     #
34398     # . prologue
34399     55/push-ebp
34400     89/<- %ebp 4/r32/esp
34401     # setup
34402     (clear-stream _test-output-stream)
34403     (clear-stream $_test-output-buffered-file->buffer)
34404 $test-add-reg-to-mem:initialize-type:
34405     # var type/ecx: (payload type-tree) = int
34406     68/push 0/imm32/right:null
34407     68/push 0/imm32/right:null
34408     68/push 0/imm32/left:unused
34409     68/push 1/imm32/value:int
34410     68/push 1/imm32/is-atom?:true
34411     68/push 0x11/imm32/alloc-id:fake:payload
34412     89/<- %ecx 4/r32/esp
34413 $test-add-reg-to-mem:initialize-var1:
34414     # var var1/ecx: (payload var)
34415     68/push 0/imm32/register
34416     68/push 0/imm32/register
34417     68/push 8/imm32/stack-offset
34418     68/push 1/imm32/block-depth
34419     51/push-ecx
34420     68/push 0x11/imm32/alloc-id:fake
34421     68/push 0/imm32/name
34422     68/push 0/imm32/name
34423     68/push 0x11/imm32/alloc-id:fake:payload
34424     89/<- %ecx 4/r32/esp
34425 $test-add-reg-to-mem:initialize-var1-name:
34426     # var1->name = "var1"
34427     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
34428     (copy-array Heap "var1" %eax)
34429 $test-add-reg-to-mem:initialize-var2:
34430     # var var2/edx: (payload var)
34431     68/push 0/imm32/register
34432     68/push 0/imm32/register
34433     68/push 0/imm32/no-stack-offset
34434     68/push 1/imm32/block-depth
34435     ff 6/subop/push *(ecx+0x10)
34436     68/push 0x11/imm32/alloc-id:fake
34437     68/push 0/imm32/name
34438     68/push 0/imm32/name
34439     68/push 0x11/imm32/alloc-id:fake:payload
34440     89/<- %edx 4/r32/esp
34441 $test-add-reg-to-mem:initialize-var2-name:
34442     # var2->name = "var2"
34443     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
34444     (copy-array Heap "var2" %eax)
34445 $test-add-reg-to-mem:initialize-var2-register:
34446     # var2->register = "ecx"
34447     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
34448     (copy-array Heap "ecx" %eax)
34449 $test-add-reg-to-mem:initialize-inouts:
34450     # var inouts/esi: (payload stmt-var) = [var2]
34451     68/push 0/imm32/is-deref:false
34452     68/push 0/imm32/next
34453     68/push 0/imm32/next
34454     52/push-edx/var2
34455     68/push 0x11/imm32/alloc-id:fake
34456     68/push 0x11/imm32/alloc-id:fake:payload
34457     89/<- %esi 4/r32/esp
34458     # inouts = [var1, var2]
34459     68/push 0/imm32/is-deref:false
34460     56/push-esi/next
34461     68/push 0x11/imm32/alloc-id:fake
34462     51/push-ecx/var1
34463     68/push 0x11/imm32/alloc-id:fake
34464     68/push 0x11/imm32/alloc-id:fake:payload
34465     89/<- %esi 4/r32/esp
34466 $test-add-reg-to-mem:initialize-stmt:
34467     # var stmt/esi: (addr statement)
34468     68/push 0/imm32/next
34469     68/push 0/imm32/next
34470     68/push 0/imm32/outputs
34471     68/push 0/imm32/outputs
34472     56/push-esi/inouts
34473     68/push 0x11/imm32/alloc-id:fake
34474     68/push 0/imm32/operation
34475     68/push 0/imm32/operation
34476     68/push 1/imm32/tag:stmt1
34477     89/<- %esi 4/r32/esp
34478 $test-add-reg-to-mem:initialize-stmt-operation:
34479     # stmt->operation = "add-to"
34480     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
34481     (copy-array Heap "add-to" %eax)
34482     # convert
34483     c7 0/subop/copy *Curr-block-depth 0/imm32
34484     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
34485     (flush _test-output-buffered-file)
34486 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
34492     # check output
34493     (check-next-stream-line-equal _test-output-stream "01/add-to *(ebp+0x00000008) 0x00000001/r32" "F - test-add-reg-to-mem")
34494     # . epilogue
34495     89/<- %esp 5/r32/ebp
34496     5d/pop-to-ebp
34497     c3/return
34498 
34499 test-add-mem-to-reg:
34500     #   var1/reg <- add var2
34501     # =>
34502     #   03/add *(ebp+__) var1
34503     #
34504     # . prologue
34505     55/push-ebp
34506     89/<- %ebp 4/r32/esp
34507     # setup
34508     (clear-stream _test-output-stream)
34509     (clear-stream $_test-output-buffered-file->buffer)
34510 $test-add-mem-to-reg:initialize-type:
34511     # var type/ecx: (payload type-tree) = int
34512     68/push 0/imm32/right:null
34513     68/push 0/imm32/right:null
34514     68/push 0/imm32/left:unused
34515     68/push 1/imm32/value:int
34516     68/push 1/imm32/is-atom?:true
34517     68/push 0x11/imm32/alloc-id:fake:payload
34518     89/<- %ecx 4/r32/esp
34519 $test-add-mem-to-reg:initialize-var:
34520     # var var1/ecx: (payload var)
34521     68/push 0/imm32/register
34522     68/push 0/imm32/register
34523     68/push 0/imm32/no-stack-offset
34524     68/push 1/imm32/block-depth
34525     51/push-ecx
34526     68/push 0x11/imm32/alloc-id:fake
34527     68/push 0/imm32/name
34528     68/push 0/imm32/name
34529     68/push 0x11/imm32/alloc-id:fake:payload
34530     89/<- %ecx 4/r32/esp
34531 $test-add-mem-to-reg:initialize-var-name:
34532     # var1->name = "foo"
34533     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
34534     (copy-array Heap "var1" %eax)
34535 $test-add-mem-to-reg:initialize-var-register:
34536     # var1->register = "eax"
34537     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
34538     (copy-array Heap "eax" %eax)
34539 $test-add-mem-to-reg:initialize-var2:
34540     # var var2/edx: (payload var)
34541     68/push 0/imm32/register
34542     68/push 0/imm32/register
34543     68/push 8/imm32/stack-offset
34544     68/push 1/imm32/block-depth
34545     ff 6/subop/push *(ecx+0x10)
34546     68/push 0x11/imm32/alloc-id:fake
34547     68/push 0/imm32/name
34548     68/push 0/imm32/name
34549     68/push 0x11/imm32/alloc-id:fake:payload
34550     89/<- %edx 4/r32/esp
34551 $test-add-mem-to-reg:initialize-var2-name:
34552     # var2->name = "var2"
34553     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
34554     (copy-array Heap "var2" %eax)
34555 $test-add-mem-to-reg:initialize-inouts:
34556     # var inouts/esi: (payload stmt-var) = [var2]
34557     68/push 0/imm32/is-deref:false
34558     68/push 0/imm32/next
34559     68/push 0/imm32/next
34560     52/push-edx/var2
34561     68/push 0x11/imm32/alloc-id:fake
34562     68/push 0x11/imm32/alloc-id:fake:payload
34563     89/<- %esi 4/r32/esp
34564 $test-add-mem-to-reg:initialize-outputs:
34565     # var outputs/edi: (payload stmt-var) = [var1]
34566     68/push 0/imm32/is-deref:false
34567     68/push 0/imm32/next
34568     68/push 0/imm32/next
34569     51/push-ecx/var1
34570     68/push 0x11/imm32/alloc-id:fake
34571     68/push 0x11/imm32/alloc-id:fake:payload
34572     89/<- %edi 4/r32/esp
34573 $test-add-mem-to-reg:initialize-stmt:
34574     # var stmt/esi: (addr statement)
34575     68/push 0/imm32/next
34576     68/push 0/imm32/next
34577     57/push-edi/outputs
34578     68/push 0x11/imm32/alloc-id:fake
34579     56/push-esi/inouts
34580     68/push 0x11/imm32/alloc-id:fake
34581     68/push 0/imm32/operation
34582     68/push 0/imm32/operation
34583     68/push 1/imm32/tag:stmt1
34584     89/<- %esi 4/r32/esp
34585 $test-add-mem-to-reg:initialize-stmt-operation:
34586     # stmt->operation = "add"
34587     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
34588     (copy-array Heap "add" %eax)
34589     # convert
34590     c7 0/subop/copy *Curr-block-depth 0/imm32
34591     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
34592     (flush _test-output-buffered-file)
34593 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
34599     # check output
34600     (check-next-stream-line-equal _test-output-stream "03/add *(ebp+0x00000008) 0x00000000/r32" "F - test-add-mem-to-reg")
34601     # . epilogue
34602     89/<- %esp 5/r32/ebp
34603     5d/pop-to-ebp
34604     c3/return
34605 
34606 test-add-literal-to-eax:
34607     #   var1/eax <- add 0x34
34608     # =>
34609     #   05/add-to-eax 0x34/imm32
34610     #
34611     # . prologue
34612     55/push-ebp
34613     89/<- %ebp 4/r32/esp
34614     # setup
34615     (clear-stream _test-output-stream)
34616     (clear-stream $_test-output-buffered-file->buffer)
34617 $test-add-literal-to-eax:initialize-var-type:
34618     # var type/ecx: (payload type-tree) = int
34619     68/push 0/imm32/right:null
34620     68/push 0/imm32/right:null
34621     68/push 0/imm32/left:unused
34622     68/push 1/imm32/value:int
34623     68/push 1/imm32/is-atom?:true
34624     68/push 0x11/imm32/alloc-id:fake:payload
34625     89/<- %ecx 4/r32/esp
34626 $test-add-literal-to-eax:initialize-var:
34627     # var v/ecx: (payload var)
34628     68/push 0/imm32/register
34629     68/push 0/imm32/register
34630     68/push 0/imm32/no-stack-offset
34631     68/push 1/imm32/block-depth
34632     51/push-ecx
34633     68/push 0x11/imm32/alloc-id:fake
34634     68/push 0/imm32/name
34635     68/push 0/imm32/name
34636     68/push 0x11/imm32/alloc-id:fake:payload
34637     89/<- %ecx 4/r32/esp
34638 $test-add-literal-to-eax:initialize-var-name:
34639     # v->name = "v"
34640     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
34641     (copy-array Heap "v" %eax)
34642 $test-add-literal-to-eax:initialize-var-register:
34643     # v->register = "eax"
34644     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
34645     (copy-array Heap "eax" %eax)
34646 $test-add-literal-to-eax:initialize-literal-type:
34647     # var type/edx: (payload type-tree) = literal
34648     68/push 0/imm32/right:null
34649     68/push 0/imm32/right:null
34650     68/push 0/imm32/left:unused
34651     68/push 0/imm32/value:literal
34652     68/push 1/imm32/is-atom?:true
34653     68/push 0x11/imm32/alloc-id:fake:payload
34654     89/<- %edx 4/r32/esp
34655 $test-add-literal-to-eax:initialize-literal:
34656     # var l/edx: (payload var)
34657     68/push 0/imm32/register
34658     68/push 0/imm32/register
34659     68/push 0/imm32/no-stack-offset
34660     68/push 1/imm32/block-depth
34661     52/push-edx
34662     68/push 0x11/imm32/alloc-id:fake
34663     68/push 0/imm32/name
34664     68/push 0/imm32/name
34665     68/push 0x11/imm32/alloc-id:fake:payload
34666     89/<- %edx 4/r32/esp
34667 $test-add-literal-to-eax:initialize-literal-value:
34668     # l->name = "0x34"
34669     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
34670     (copy-array Heap "0x34" %eax)
34671 $test-add-literal-to-eax:initialize-inouts:
34672     # var inouts/esi: (payload stmt-var) = [l]
34673     68/push 0/imm32/is-deref:false
34674     68/push 0/imm32/next
34675     68/push 0/imm32/next
34676     52/push-edx/l
34677     68/push 0x11/imm32/alloc-id:fake
34678     68/push 0x11/imm32/alloc-id:fake:payload
34679     89/<- %esi 4/r32/esp
34680 $test-add-literal-to-eax:initialize-outputs:
34681     # var outputs/edi: (payload stmt-var) = [v]
34682     68/push 0/imm32/is-deref:false
34683     68/push 0/imm32/next
34684     68/push 0/imm32/next
34685     51/push-ecx/v
34686     68/push 0x11/imm32/alloc-id:fake
34687     68/push 0x11/imm32/alloc-id:fake:payload
34688     89/<- %edi 4/r32/esp
34689 $test-add-literal-to-eax:initialize-stmt:
34690     # var stmt/esi: (addr statement)
34691     68/push 0/imm32/next
34692     68/push 0/imm32/next
34693     57/push-edi/outputs
34694     68/push 0x11/imm32/alloc-id:fake
34695     56/push-esi/inouts
34696     68/push 0x11/imm32/alloc-id:fake
34697     68/push 0/imm32/operation
34698     68/push 0/imm32/operation
34699     68/push 1/imm32/tag:stmt1
34700     89/<- %esi 4/r32/esp
34701 $test-add-literal-to-eax:initialize-stmt-operation:
34702     # stmt->operation = "add"
34703     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
34704     (copy-array Heap "add" %eax)
34705     # convert
34706     c7 0/subop/copy *Curr-block-depth 0/imm32
34707     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
34708     (flush _test-output-buffered-file)
34709 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
34715     # check output
34716     (check-next-stream-line-equal _test-output-stream "05/add-to-eax 0x34/imm32" "F - test-add-literal-to-eax")
34717     # . epilogue
34718     89/<- %esp 5/r32/ebp
34719     5d/pop-to-ebp
34720     c3/return
34721 
34722 test-add-literal-to-reg:
34723     #   var1/ecx <- add 0x34
34724     # =>
34725     #   81 0/subop/add %ecx 0x34/imm32
34726     #
34727     # . prologue
34728     55/push-ebp
34729     89/<- %ebp 4/r32/esp
34730     # setup
34731     (clear-stream _test-output-stream)
34732     (clear-stream $_test-output-buffered-file->buffer)
34733 $test-add-literal-to-reg:initialize-var-type:
34734     # var type/ecx: (payload type-tree) = int
34735     68/push 0/imm32/right:null
34736     68/push 0/imm32/right:null
34737     68/push 0/imm32/left:unused
34738     68/push 1/imm32/value:int
34739     68/push 1/imm32/is-atom?:true
34740     68/push 0x11/imm32/alloc-id:fake:payload
34741     89/<- %ecx 4/r32/esp
34742 $test-add-literal-to-reg:initialize-var:
34743     # var v/ecx: (payload var)
34744     68/push 0/imm32/register
34745     68/push 0/imm32/register
34746     68/push 0/imm32/no-stack-offset
34747     68/push 1/imm32/block-depth
34748     51/push-ecx
34749     68/push 0x11/imm32/alloc-id:fake
34750     68/push 0/imm32/name
34751     68/push 0/imm32/name
34752     68/push 0x11/imm32/alloc-id:fake:payload
34753     89/<- %ecx 4/r32/esp
34754 $test-add-literal-to-reg:initialize-var-name:
34755     # v->name = "v"
34756     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
34757     (copy-array Heap "v" %eax)
34758 $test-add-literal-to-reg:initialize-var-register:
34759     # v->register = "ecx"
34760     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
34761     (copy-array Heap "ecx" %eax)
34762 $test-add-literal-to-reg:initialize-literal-type:
34763     # var type/edx: (payload type-tree) = literal
34764     68/push 0/imm32/right:null
34765     68/push 0/imm32/right:null
34766     68/push 0/imm32/left:unused
34767     68/push 0/imm32/value:literal
34768     68/push 1/imm32/is-atom?:true
34769     68/push 0x11/imm32/alloc-id:fake:payload
34770     89/<- %edx 4/r32/esp
34771 $test-add-literal-to-reg:initialize-literal:
34772     # var l/edx: (payload var)
34773     68/push 0/imm32/register
34774     68/push 0/imm32/register
34775     68/push 0/imm32/no-stack-offset
34776     68/push 1/imm32/block-depth
34777     52/push-edx
34778     68/push 0x11/imm32/alloc-id:fake
34779     68/push 0/imm32/name
34780     68/push 0/imm32/name
34781     68/push 0x11/imm32/alloc-id:fake:payload
34782     89/<- %edx 4/r32/esp
34783 $test-add-literal-to-reg:initialize-literal-value:
34784     # l->name = "0x34"
34785     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
34786     (copy-array Heap "0x34" %eax)
34787 $test-add-literal-to-reg:initialize-inouts:
34788     # var inouts/esi: (payload stmt-var) = [l]
34789     68/push 0/imm32/is-deref:false
34790     68/push 0/imm32/next
34791     68/push 0/imm32/next
34792     52/push-edx/l
34793     68/push 0x11/imm32/alloc-id:fake
34794     68/push 0x11/imm32/alloc-id:fake:payload
34795     89/<- %esi 4/r32/esp
34796 $test-add-literal-to-reg:initialize-outputs:
34797     # var outputs/edi: (payload stmt-var) = [v]
34798     68/push 0/imm32/is-deref:false
34799     68/push 0/imm32/next
34800     68/push 0/imm32/next
34801     51/push-ecx/v
34802     68/push 0x11/imm32/alloc-id:fake
34803     68/push 0x11/imm32/alloc-id:fake:payload
34804     89/<- %edi 4/r32/esp
34805 $test-add-literal-to-reg:initialize-stmt:
34806     # var stmt/esi: (addr statement)
34807     68/push 0/imm32/next
34808     68/push 0/imm32/next
34809     57/push-edi/outputs
34810     68/push 0x11/imm32/alloc-id:fake
34811     56/push-esi/inouts
34812     68/push 0x11/imm32/alloc-id:fake
34813     68/push 0/imm32/operation
34814     68/push 0/imm32/operation
34815     68/push 1/imm32/tag:stmt1
34816     89/<- %esi 4/r32/esp
34817 $test-add-literal-to-reg:initialize-stmt-operation:
34818     # stmt->operation = "add"
34819     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
34820     (copy-array Heap "add" %eax)
34821     # convert
34822     c7 0/subop/copy *Curr-block-depth 0/imm32
34823     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
34824     (flush _test-output-buffered-file)
34825 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
34831     # check output
34832     (check-next-stream-line-equal _test-output-stream "81 0/subop/add %ecx 0x34/imm32" "F - test-add-literal-to-reg")
34833     # . epilogue
34834     89/<- %esp 5/r32/ebp
34835     5d/pop-to-ebp
34836     c3/return
34837 
34838 test-add-literal-to-mem:
34839     #   add-to var1, 0x34
34840     # =>
34841     #   81 0/subop/add %eax 0x34/imm32
34842     #
34843     # . prologue
34844     55/push-ebp
34845     89/<- %ebp 4/r32/esp
34846     # setup
34847     (clear-stream _test-output-stream)
34848     (clear-stream $_test-output-buffered-file->buffer)
34849 $test-add-literal-to-mem:initialize-type:
34850     # var type/ecx: (payload type-tree) = int
34851     68/push 0/imm32/right:null
34852     68/push 0/imm32/right:null
34853     68/push 0/imm32/left:unused
34854     68/push 1/imm32/value:int
34855     68/push 1/imm32/is-atom?:true
34856     68/push 0x11/imm32/alloc-id:fake:payload
34857     89/<- %ecx 4/r32/esp
34858 $test-add-literal-to-mem:initialize-var1:
34859     # var var1/ecx: (payload var)
34860     68/push 0/imm32/register
34861     68/push 0/imm32/register
34862     68/push 8/imm32/stack-offset
34863     68/push 1/imm32/block-depth
34864     51/push-ecx
34865     68/push 0x11/imm32/alloc-id:fake
34866     68/push 0/imm32/name
34867     68/push 0/imm32/name
34868     68/push 0x11/imm32/alloc-id:fake:payload
34869     89/<- %ecx 4/r32/esp
34870 $test-add-literal-to-mem:initialize-var1-name:
34871     # var1->name = "var1"
34872     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
34873     (copy-array Heap "var1" %eax)
34874 $test-add-literal-to-mem:initialize-literal-type:
34875     # var type/edx: (payload type-tree) = literal
34876     68/push 0/imm32/right:null
34877     68/push 0/imm32/right:null
34878     68/push 0/imm32/left:unused
34879     68/push 0/imm32/value:literal
34880     68/push 1/imm32/is-atom?:true
34881     68/push 0x11/imm32/alloc-id:fake:payload
34882     89/<- %edx 4/r32/esp
34883 $test-add-literal-to-mem:initialize-literal:
34884     # var l/edx: (payload var)
34885     68/push 0/imm32/register
34886     68/push 0/imm32/register
34887     68/push 0/imm32/no-stack-offset
34888     68/push 1/imm32/block-depth
34889     52/push-edx
34890     68/push 0x11/imm32/alloc-id:fake
34891     68/push 0/imm32/name
34892     68/push 0/imm32/name
34893     68/push 0x11/imm32/alloc-id:fake:payload
34894     89/<- %edx 4/r32/esp
34895 $test-add-literal-to-mem:initialize-literal-value:
34896     # l->name = "0x34"
34897     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
34898     (copy-array Heap "0x34" %eax)
34899 $test-add-literal-to-mem:initialize-inouts:
34900     # var inouts/esi: (payload stmt-var) = [l]
34901     68/push 0/imm32/is-deref:false
34902     68/push 0/imm32/next
34903     68/push 0/imm32/next
34904     52/push-edx/l
34905     68/push 0x11/imm32/alloc-id:fake
34906     68/push 0x11/imm32/alloc-id:fake:payload
34907     89/<- %esi 4/r32/esp
34908     # var inouts = (handle stmt-var) = [var1, var2]
34909     68/push 0/imm32/is-deref:false
34910     56/push-esi/next
34911     68/push 0x11/imm32/alloc-id:fake
34912     51/push-ecx/var1
34913     68/push 0x11/imm32/alloc-id:fake
34914     68/push 0x11/imm32/alloc-id:fake:payload
34915     89/<- %esi 4/r32/esp
34916 $test-add-literal-to-mem:initialize-stmt:
34917     # var stmt/esi: (addr statement)
34918     68/push 0/imm32/next
34919     68/push 0/imm32/next
34920     68/push 0/imm32/outputs
34921     68/push 0/imm32/outputs
34922     56/push-esi/inouts
34923     68/push 0x11/imm32/alloc-id:fake
34924     68/push 0/imm32/operation
34925     68/push 0/imm32/operation
34926     68/push 1/imm32/tag:stmt1
34927     89/<- %esi 4/r32/esp
34928 $test-add-literal-to-mem:initialize-stmt-operation:
34929     # stmt->operation = "add-to"
34930     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
34931     (copy-array Heap "add-to" %eax)
34932     # convert
34933     c7 0/subop/copy *Curr-block-depth 0/imm32
34934     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
34935     (flush _test-output-buffered-file)
34936 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
34942     # check output
34943     (check-next-stream-line-equal _test-output-stream "81 0/subop/add *(ebp+0x00000008) 0x34/imm32" "F - test-add-literal-to-mem")
34944     # . epilogue
34945     89/<- %esp 5/r32/ebp
34946     5d/pop-to-ebp
34947     c3/return
34948 
34949 test-shift-reg-by-literal:
34950     #   var1/ecx <- shift-left 2
34951     # =>
34952     #   c1/shift 4/subop/left %ecx 2/imm8
34953     #
34954     # . prologue
34955     55/push-ebp
34956     89/<- %ebp 4/r32/esp
34957     # setup
34958     (clear-stream _test-output-stream)
34959     (clear-stream $_test-output-buffered-file->buffer)
34960 $test-shift-reg-by-literal:initialize-var-type:
34961     # var type/ecx: (payload type-tree) = int
34962     68/push 0/imm32/right:null
34963     68/push 0/imm32/right:null
34964     68/push 0/imm32/left:unused
34965     68/push 1/imm32/value:int
34966     68/push 1/imm32/is-atom?:true
34967     68/push 0x11/imm32/alloc-id:fake:payload
34968     89/<- %ecx 4/r32/esp
34969 $test-shift-reg-by-literal:initialize-var:
34970     # var v/ecx: (payload var)
34971     68/push 0/imm32/register
34972     68/push 0/imm32/register
34973     68/push 0/imm32/no-stack-offset
34974     68/push 1/imm32/block-depth
34975     51/push-ecx
34976     68/push 0x11/imm32/alloc-id:fake
34977     68/push 0/imm32/name
34978     68/push 0/imm32/name
34979     68/push 0x11/imm32/alloc-id:fake:payload
34980     89/<- %ecx 4/r32/esp
34981 $test-shift-reg-by-literal:initialize-var-name:
34982     # v->name = "v"
34983     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
34984     (copy-array Heap "v" %eax)
34985 $test-shift-reg-by-literal:initialize-var-register:
34986     # v->register = "ecx"
34987     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
34988     (copy-array Heap "ecx" %eax)
34989 $test-shift-reg-by-literal:initialize-literal-type:
34990     # var type/edx: (payload type-tree) = literal
34991     68/push 0/imm32/right:null
34992     68/push 0/imm32/right:null
34993     68/push 0/imm32/left:unused
34994     68/push 0/imm32/value:literal
34995     68/push 1/imm32/is-atom?:true
34996     68/push 0x11/imm32/alloc-id:fake:payload
34997     89/<- %edx 4/r32/esp
34998 $test-shift-reg-by-literal:initialize-literal:
34999     # var l/edx: (payload var)
35000     68/push 0/imm32/register
35001     68/push 0/imm32/register
35002     68/push 0/imm32/no-stack-offset
35003     68/push 1/imm32/block-depth
35004     52/push-edx
35005     68/push 0x11/imm32/alloc-id:fake
35006     68/push 0/imm32/name
35007     68/push 0/imm32/name
35008     68/push 0x11/imm32/alloc-id:fake:payload
35009     89/<- %edx 4/r32/esp
35010 $test-shift-reg-by-literal:initialize-literal-value:
35011     # l->name = "2"
35012     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
35013     (copy-array Heap "2" %eax)
35014 $test-shift-reg-by-literal:initialize-inouts:
35015     # var inouts/esi: (payload stmt-var) = [l]
35016     68/push 0/imm32/is-deref:false
35017     68/push 0/imm32/next
35018     68/push 0/imm32/next
35019     52/push-edx/l
35020     68/push 0x11/imm32/alloc-id:fake
35021     68/push 0x11/imm32/alloc-id:fake:payload
35022     89/<- %esi 4/r32/esp
35023 $test-shift-reg-by-literal:initialize-outputs:
35024     # var outputs/edi: (payload stmt-var) = [v]
35025     68/push 0/imm32/is-deref:false
35026     68/push 0/imm32/next
35027     68/push 0/imm32/next
35028     51/push-ecx/v
35029     68/push 0x11/imm32/alloc-id:fake
35030     68/push 0x11/imm32/alloc-id:fake:payload
35031     89/<- %edi 4/r32/esp
35032 $test-shift-reg-by-literal:initialize-stmt:
35033     # var stmt/esi: (addr statement)
35034     68/push 0/imm32/next
35035     68/push 0/imm32/next
35036     57/push-edi/outputs
35037     68/push 0x11/imm32/alloc-id:fake
35038     56/push-esi/inouts
35039     68/push 0x11/imm32/alloc-id:fake
35040     68/push 0/imm32/operation
35041     68/push 0/imm32/operation
35042     68/push 1/imm32/tag:stmt1
35043     89/<- %esi 4/r32/esp
35044 $test-shift-reg-by-literal:initialize-stmt-operation:
35045     # stmt->operation = "shift-left"
35046     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
35047     (copy-array Heap "shift-left" %eax)
35048     # convert
35049     c7 0/subop/copy *Curr-block-depth 0/imm32
35050     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
35051     (flush _test-output-buffered-file)
35052 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
35058     # check output
35059     (check-next-stream-line-equal _test-output-stream "c1/shift 4/subop/left %ecx 2/imm8" "F - test-shift-reg-by-literal")
35060     # . epilogue
35061     89/<- %esp 5/r32/ebp
35062     5d/pop-to-ebp
35063     c3/return
35064 
35065 test-shift-mem-by-literal:
35066     #   shift-left var 3
35067     # =>
35068     #   c1/shift 4/subop/left *(ebp+8) 3/imm8
35069     #
35070     # . prologue
35071     55/push-ebp
35072     89/<- %ebp 4/r32/esp
35073     # setup
35074     (clear-stream _test-output-stream)
35075     (clear-stream $_test-output-buffered-file->buffer)
35076 $test-shift-mem-by-literal:initialize-type:
35077     # var type/ecx: (payload type-tree) = int
35078     68/push 0/imm32/right:null
35079     68/push 0/imm32/right:null
35080     68/push 0/imm32/left:unused
35081     68/push 1/imm32/value:int
35082     68/push 1/imm32/is-atom?:true
35083     68/push 0x11/imm32/alloc-id:fake:payload
35084     89/<- %ecx 4/r32/esp
35085 $test-shift-mem-by-literal:initialize-var1:
35086     # var var1/ecx: (payload var)
35087     68/push 0/imm32/register
35088     68/push 0/imm32/register
35089     68/push 8/imm32/stack-offset
35090     68/push 1/imm32/block-depth
35091     51/push-ecx
35092     68/push 0x11/imm32/alloc-id:fake
35093     68/push 0/imm32/name
35094     68/push 0/imm32/name
35095     68/push 0x11/imm32/alloc-id:fake:payload
35096     89/<- %ecx 4/r32/esp
35097 $test-shift-mem-by-literal:initialize-var1-name:
35098     # var1->name = "var1"
35099     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
35100     (copy-array Heap "var1" %eax)
35101 $test-shift-mem-by-literal:initialize-literal-type:
35102     # var type/edx: (payload type-tree) = literal
35103     68/push 0/imm32/right:null
35104     68/push 0/imm32/right:null
35105     68/push 0/imm32/left:unused
35106     68/push 0/imm32/value:literal
35107     68/push 1/imm32/is-atom?:true
35108     68/push 0x11/imm32/alloc-id:fake:payload
35109     89/<- %edx 4/r32/esp
35110 $test-shift-mem-by-literal:initialize-literal:
35111     # var l/edx: (payload var)
35112     68/push 0/imm32/register
35113     68/push 0/imm32/register
35114     68/push 0/imm32/no-stack-offset
35115     68/push 1/imm32/block-depth
35116     52/push-edx
35117     68/push 0x11/imm32/alloc-id:fake
35118     68/push 0/imm32/name
35119     68/push 0/imm32/name
35120     68/push 0x11/imm32/alloc-id:fake:payload
35121     89/<- %edx 4/r32/esp
35122 $test-shift-mem-by-literal:initialize-literal-value:
35123     # l->name = "3"
35124     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
35125     (copy-array Heap "3" %eax)
35126 $test-shift-mem-by-literal:initialize-inouts:
35127     # var inouts/esi: (payload stmt-var) = [l]
35128     68/push 0/imm32/is-deref:false
35129     68/push 0/imm32/next
35130     68/push 0/imm32/next
35131     52/push-edx/l
35132     68/push 0x11/imm32/alloc-id:fake
35133     68/push 0x11/imm32/alloc-id:fake:payload
35134     89/<- %esi 4/r32/esp
35135     # var inouts = (handle stmt-var) = [var1, var2]
35136     68/push 0/imm32/is-deref:false
35137     56/push-esi/next
35138     68/push 0x11/imm32/alloc-id:fake
35139     51/push-ecx/var1
35140     68/push 0x11/imm32/alloc-id:fake
35141     68/push 0x11/imm32/alloc-id:fake:payload
35142     89/<- %esi 4/r32/esp
35143 $test-shift-mem-by-literal:initialize-stmt:
35144     # var stmt/esi: (addr statement)
35145     68/push 0/imm32/next
35146     68/push 0/imm32/next
35147     68/push 0/imm32/outputs
35148     68/push 0/imm32/outputs
35149     56/push-esi/inouts
35150     68/push 0x11/imm32/alloc-id:fake
35151     68/push 0/imm32/operation
35152     68/push 0/imm32/operation
35153     68/push 1/imm32/tag:stmt1
35154     89/<- %esi 4/r32/esp
35155 $test-shift-mem-by-literal:initialize-stmt-operation:
35156     # stmt->operation = "shift-left"
35157     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
35158     (copy-array Heap "shift-left" %eax)
35159     # convert
35160     c7 0/subop/copy *Curr-block-depth 0/imm32
35161     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
35162     (flush _test-output-buffered-file)
35163 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
35169     # check output
35170     (check-next-stream-line-equal _test-output-stream "c1/shift 4/subop/left *(ebp+0x00000008) 3/imm8" "F - test-shift-mem-by-literal")
35171     # . epilogue
35172     89/<- %esp 5/r32/ebp
35173     5d/pop-to-ebp
35174     c3/return
35175 
35176 test-compare-reg-with-reg:
35177     #   compare var1/ecx, var2/eax
35178     # =>
35179     #   39/compare %ecx 0/r32/eax
35180     #
35181     # . prologue
35182     55/push-ebp
35183     89/<- %ebp 4/r32/esp
35184     # setup
35185     (clear-stream _test-output-stream)
35186     (clear-stream $_test-output-buffered-file->buffer)
35187 $test-compare-reg-with-reg:initialize-type:
35188     # var type/ecx: (payload type-tree) = int
35189     68/push 0/imm32/right:null
35190     68/push 0/imm32/right:null
35191     68/push 0/imm32/left:unused
35192     68/push 1/imm32/value:int
35193     68/push 1/imm32/is-atom?:true
35194     68/push 0x11/imm32/alloc-id:fake:payload
35195     89/<- %ecx 4/r32/esp
35196 $test-compare-reg-with-reg:initialize-var1:
35197     # var var1/ecx: (payload var)
35198     68/push 0/imm32/register
35199     68/push 0/imm32/register
35200     68/push 0/imm32/no-stack-offset
35201     68/push 1/imm32/block-depth
35202     51/push-ecx
35203     68/push 0x11/imm32/alloc-id:fake
35204     68/push 0/imm32/name
35205     68/push 0/imm32/name
35206     68/push 0x11/imm32/alloc-id:fake:payload
35207     89/<- %ecx 4/r32/esp
35208 $test-compare-reg-with-reg:initialize-var1-name:
35209     # var1->name = "var1"
35210     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
35211     (copy-array Heap "var1" %eax)
35212 $test-compare-reg-with-reg:initialize-var1-register:
35213     # var1->register = "ecx"
35214     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
35215     (copy-array Heap "ecx" %eax)
35216 $test-compare-reg-with-reg:initialize-var2:
35217     # var var2/edx: (payload var)
35218     68/push 0/imm32/register
35219     68/push 0/imm32/register
35220     68/push 0/imm32/no-stack-offset
35221     68/push 1/imm32/block-depth
35222     ff 6/subop/push *(ecx+0x10)
35223     68/push 0x11/imm32/alloc-id:fake
35224     68/push 0/imm32/name
35225     68/push 0/imm32/name
35226     68/push 0x11/imm32/alloc-id:fake:payload
35227     89/<- %edx 4/r32/esp
35228 $test-compare-reg-with-reg:initialize-var2-name:
35229     # var2->name = "var2"
35230     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
35231     (copy-array Heap "var2" %eax)
35232 $test-compare-reg-with-reg:initialize-var2-register:
35233     # var2->register = "eax"
35234     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
35235     (copy-array Heap "eax" %eax)
35236 $test-compare-reg-with-reg:initialize-inouts:
35237     # var inouts/esi: (payload stmt-var) = [var2]
35238     68/push 0/imm32/is-deref:false
35239     68/push 0/imm32/next
35240     68/push 0/imm32/next
35241     52/push-edx/var2
35242     68/push 0x11/imm32/alloc-id:fake
35243     68/push 0x11/imm32/alloc-id:fake:payload
35244     89/<- %esi 4/r32/esp
35245     # inouts = [var1, var2]
35246     68/push 0/imm32/is-deref:false
35247     56/push-esi/next
35248     68/push 0x11/imm32/alloc-id:fake
35249     51/push-ecx/var1
35250     68/push 0x11/imm32/alloc-id:fake
35251     68/push 0x11/imm32/alloc-id:fake:payload
35252     89/<- %esi 4/r32/esp
35253 $test-compare-reg-with-reg:initialize-stmt:
35254     # var stmt/esi: (addr statement)
35255     68/push 0/imm32/next
35256     68/push 0/imm32/next
35257     68/push 0/imm32/outputs
35258     68/push 0/imm32/outputs
35259     56/push-esi/inouts
35260     68/push 0x11/imm32/alloc-id:fake
35261     68/push 0/imm32/operation
35262     68/push 0/imm32/operation
35263     68/push 1/imm32/tag:stmt1
35264     89/<- %esi 4/r32/esp
35265 $test-compare-reg-with-reg:initialize-stmt-operation:
35266     # stmt->operation = "compare"
35267     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
35268     (copy-array Heap "compare" %eax)
35269     # convert
35270     c7 0/subop/copy *Curr-block-depth 0/imm32
35271     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
35272     (flush _test-output-buffered-file)
35273 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
35279     # check output
35280     (check-next-stream-line-equal _test-output-stream "39/compare-> %ecx 0x00000000/r32" "F - test-compare-reg-with-reg")
35281     # . epilogue
35282     89/<- %esp 5/r32/ebp
35283     5d/pop-to-ebp
35284     c3/return
35285 
35286 test-compare-mem-with-reg:
35287     #   compare var1, var2/eax
35288     # =>
35289     #   39/compare *(ebp+___) 0/r32/eax
35290     #
35291     # . prologue
35292     55/push-ebp
35293     89/<- %ebp 4/r32/esp
35294     # setup
35295     (clear-stream _test-output-stream)
35296     (clear-stream $_test-output-buffered-file->buffer)
35297 $test-compare-mem-with-reg:initialize-type:
35298     # var type/ecx: (payload type-tree) = int
35299     68/push 0/imm32/right:null
35300     68/push 0/imm32/right:null
35301     68/push 0/imm32/left:unused
35302     68/push 1/imm32/value:int
35303     68/push 1/imm32/is-atom?:true
35304     68/push 0x11/imm32/alloc-id:fake:payload
35305     89/<- %ecx 4/r32/esp
35306 $test-compare-mem-with-reg:initialize-var1:
35307     # var var1/ecx: (payload var)
35308     68/push 0/imm32/register
35309     68/push 0/imm32/register
35310     68/push 8/imm32/stack-offset
35311     68/push 1/imm32/block-depth
35312     51/push-ecx
35313     68/push 0x11/imm32/alloc-id:fake
35314     68/push 0/imm32/name
35315     68/push 0/imm32/name
35316     68/push 0x11/imm32/alloc-id:fake:payload
35317     89/<- %ecx 4/r32/esp
35318 $test-compare-mem-with-reg:initialize-var1-name:
35319     # var1->name = "var1"
35320     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
35321     (copy-array Heap "var1" %eax)
35322 $test-compare-mem-with-reg:initialize-var2:
35323     # var var2/edx: (payload var)
35324     68/push 0/imm32/register
35325     68/push 0/imm32/register
35326     68/push 0/imm32/no-stack-offset
35327     68/push 1/imm32/block-depth
35328     ff 6/subop/push *(ecx+0x10)
35329     68/push 0x11/imm32/alloc-id:fake
35330     68/push 0/imm32/name
35331     68/push 0/imm32/name
35332     68/push 0x11/imm32/alloc-id:fake:payload
35333     89/<- %edx 4/r32/esp
35334 $test-compare-mem-with-reg:initialize-var2-name:
35335     # var2->name = "var2"
35336     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
35337     (copy-array Heap "var2" %eax)
35338 $test-compare-mem-with-reg:initialize-var2-register:
35339     # var2->register = "eax"
35340     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
35341     (copy-array Heap "eax" %eax)
35342 $test-compare-mem-with-reg:initialize-inouts:
35343     # var inouts/esi: (payload stmt-var) = [var2]
35344     68/push 0/imm32/is-deref:false
35345     68/push 0/imm32/next
35346     68/push 0/imm32/next
35347     52/push-edx/var2
35348     68/push 0x11/imm32/alloc-id:fake
35349     68/push 0x11/imm32/alloc-id:fake:payload
35350     89/<- %esi 4/r32/esp
35351     # inouts = [var1, var2]
35352     68/push 0/imm32/is-deref:false
35353     56/push-esi/next
35354     68/push 0x11/imm32/alloc-id:fake
35355     51/push-ecx/var1
35356     68/push 0x11/imm32/alloc-id:fake
35357     68/push 0x11/imm32/alloc-id:fake:payload
35358     89/<- %esi 4/r32/esp
35359 $test-compare-mem-with-reg:initialize-stmt:
35360     # var stmt/esi: (addr statement)
35361     68/push 0/imm32/next
35362     68/push 0/imm32/next
35363     68/push 0/imm32/outputs
35364     68/push 0/imm32/outputs
35365     56/push-esi/inouts
35366     68/push 0x11/imm32/alloc-id:fake
35367     68/push 0/imm32/operation
35368     68/push 0/imm32/operation
35369     68/push 1/imm32/tag:stmt1
35370     89/<- %esi 4/r32/esp
35371 $test-compare-mem-with-reg:initialize-stmt-operation:
35372     # stmt->operation = "compare"
35373     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
35374     (copy-array Heap "compare" %eax)
35375     # convert
35376     c7 0/subop/copy *Curr-block-depth 0/imm32
35377     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
35378     (flush _test-output-buffered-file)
35379 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
35385     # check output
35386     (check-next-stream-line-equal _test-output-stream "39/compare-> *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-mem-with-reg")
35387     # . epilogue
35388     89/<- %esp 5/r32/ebp
35389     5d/pop-to-ebp
35390     c3/return
35391 
35392 test-compare-reg-with-mem:
35393     #   compare var1/eax, var2
35394     # =>
35395     #   3b/compare<- *(ebp+___) 0/r32/eax
35396     #
35397     # . prologue
35398     55/push-ebp
35399     89/<- %ebp 4/r32/esp
35400     # setup
35401     (clear-stream _test-output-stream)
35402     (clear-stream $_test-output-buffered-file->buffer)
35403 $test-compare-reg-with-mem:initialize-type:
35404     # var type/ecx: (payload type-tree) = int
35405     68/push 0/imm32/right:null
35406     68/push 0/imm32/right:null
35407     68/push 0/imm32/left:unused
35408     68/push 1/imm32/value:int
35409     68/push 1/imm32/is-atom?:true
35410     68/push 0x11/imm32/alloc-id:fake:payload
35411     89/<- %ecx 4/r32/esp
35412 $test-compare-reg-with-mem:initialize-var1:
35413     # var var1/ecx: (payload var)
35414     68/push 0/imm32/register
35415     68/push 0/imm32/register
35416     68/push 0/imm32/no-stack-offset
35417     68/push 1/imm32/block-depth
35418     51/push-ecx
35419     68/push 0x11/imm32/alloc-id:fake
35420     68/push 0/imm32/name
35421     68/push 0/imm32/name
35422     68/push 0x11/imm32/alloc-id:fake:payload
35423     89/<- %ecx 4/r32/esp
35424 $test-compare-reg-with-mem:initialize-var1-name:
35425     # var1->name = "var1"
35426     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
35427     (copy-array Heap "var1" %eax)
35428 $test-compare-reg-with-mem:initialize-var1-register:
35429     # var1->register = "eax"
35430     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
35431     (copy-array Heap "eax" %eax)
35432 $test-compare-reg-with-mem:initialize-var2:
35433     # var var2/edx: (payload var)
35434     68/push 0/imm32/register
35435     68/push 0/imm32/register
35436     68/push 8/imm32/stack-offset
35437     68/push 1/imm32/block-depth
35438     ff 6/subop/push *(ecx+0x10)
35439     68/push 0x11/imm32/alloc-id:fake
35440     68/push 0/imm32/name
35441     68/push 0/imm32/name
35442     68/push 0x11/imm32/alloc-id:fake:payload
35443     89/<- %edx 4/r32/esp
35444 $test-compare-reg-with-mem:initialize-var2-name:
35445     # var2->name = "var2"
35446     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
35447     (copy-array Heap "var2" %eax)
35448 $test-compare-reg-with-mem:initialize-inouts:
35449     # var inouts/esi: (payload stmt-var) = [var2]
35450     68/push 0/imm32/is-deref:false
35451     68/push 0/imm32/next
35452     68/push 0/imm32/next
35453     52/push-edx/var2
35454     68/push 0x11/imm32/alloc-id:fake
35455     68/push 0x11/imm32/alloc-id:fake:payload
35456     89/<- %esi 4/r32/esp
35457     # inouts = [var1, var2]
35458     68/push 0/imm32/is-deref:false
35459     56/push-esi/next
35460     68/push 0x11/imm32/alloc-id:fake
35461     51/push-ecx/var1
35462     68/push 0x11/imm32/alloc-id:fake
35463     68/push 0x11/imm32/alloc-id:fake:payload
35464     89/<- %esi 4/r32/esp
35465 $test-compare-reg-with-mem:initialize-stmt:
35466     # var stmt/esi: (addr statement)
35467     68/push 0/imm32/next
35468     68/push 0/imm32/next
35469     68/push 0/imm32/outputs
35470     68/push 0/imm32/outputs
35471     56/push-esi/inouts
35472     68/push 0x11/imm32/alloc-id:fake
35473     68/push 0/imm32/operation
35474     68/push 0/imm32/operation
35475     68/push 1/imm32/tag:stmt1
35476     89/<- %esi 4/r32/esp
35477 $test-compare-reg-with-mem:initialize-stmt-operation:
35478     # stmt->operation = "compare"
35479     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
35480     (copy-array Heap "compare" %eax)
35481     # convert
35482     c7 0/subop/copy *Curr-block-depth 0/imm32
35483     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
35484     (flush _test-output-buffered-file)
35485 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
35491     # check output
35492     (check-next-stream-line-equal _test-output-stream "3b/compare<- *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-reg-with-mem")
35493     # . epilogue
35494     89/<- %esp 5/r32/ebp
35495     5d/pop-to-ebp
35496     c3/return
35497 
35498 test-compare-mem-with-literal:
35499     #   compare var1, 0x34
35500     # =>
35501     #   81 7/subop/compare *(ebp+___) 0x34/imm32
35502     #
35503     # . prologue
35504     55/push-ebp
35505     89/<- %ebp 4/r32/esp
35506     # setup
35507     (clear-stream _test-output-stream)
35508     (clear-stream $_test-output-buffered-file->buffer)
35509 $test-compare-mem-with-literal:initialize-type:
35510     # var type/ecx: (payload type-tree) = int
35511     68/push 0/imm32/right:null
35512     68/push 0/imm32/right:null
35513     68/push 0/imm32/left:unused
35514     68/push 1/imm32/value:int
35515     68/push 1/imm32/is-atom?:true
35516     68/push 0x11/imm32/alloc-id:fake:payload
35517     89/<- %ecx 4/r32/esp
35518 $test-compare-mem-with-literal:initialize-var1:
35519     # var var1/ecx: (payload var)
35520     68/push 0/imm32/register
35521     68/push 0/imm32/register
35522     68/push 8/imm32/stack-offset
35523     68/push 1/imm32/block-depth
35524     51/push-ecx
35525     68/push 0x11/imm32/alloc-id:fake
35526     68/push 0/imm32/name
35527     68/push 0/imm32/name
35528     68/push 0x11/imm32/alloc-id:fake:payload
35529     89/<- %ecx 4/r32/esp
35530 $test-compare-mem-with-literal:initialize-var1-name:
35531     # var1->name = "var1"
35532     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
35533     (copy-array Heap "var1" %eax)
35534 $test-compare-mem-with-literal:initialize-literal-type:
35535     # var type/edx: (payload type-tree) = literal
35536     68/push 0/imm32/right:null
35537     68/push 0/imm32/right:null
35538     68/push 0/imm32/left:unused
35539     68/push 0/imm32/value:literal
35540     68/push 1/imm32/is-atom?:true
35541     68/push 0x11/imm32/alloc-id:fake:payload
35542     89/<- %edx 4/r32/esp
35543 $test-compare-mem-with-literal:initialize-literal:
35544     # var l/edx: (payload var)
35545     68/push 0/imm32/register
35546     68/push 0/imm32/register
35547     68/push 0/imm32/no-stack-offset
35548     68/push 1/imm32/block-depth
35549     52/push-edx
35550     68/push 0x11/imm32/alloc-id:fake
35551     68/push 0/imm32/name
35552     68/push 0/imm32/name
35553     68/push 0x11/imm32/alloc-id:fake:payload
35554     89/<- %edx 4/r32/esp
35555 $test-compare-mem-with-literal:initialize-literal-value:
35556     # l->name = "0x34"
35557     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
35558     (copy-array Heap "0x34" %eax)
35559 $test-compare-mem-with-literal:initialize-inouts:
35560     # var inouts/esi: (payload stmt-var) = [l]
35561     68/push 0/imm32/is-deref:false
35562     68/push 0/imm32/next
35563     68/push 0/imm32/next
35564     52/push-edx/l
35565     68/push 0x11/imm32/alloc-id:fake
35566     68/push 0x11/imm32/alloc-id:fake:payload
35567     89/<- %esi 4/r32/esp
35568     # var inouts = (handle stmt-var) = [var1, var2]
35569     68/push 0/imm32/is-deref:false
35570     56/push-esi/next
35571     68/push 0x11/imm32/alloc-id:fake
35572     51/push-ecx/var1
35573     68/push 0x11/imm32/alloc-id:fake
35574     68/push 0x11/imm32/alloc-id:fake:payload
35575     89/<- %esi 4/r32/esp
35576 $test-compare-mem-with-literal:initialize-stmt:
35577     # var stmt/esi: (addr statement)
35578     68/push 0/imm32/next
35579     68/push 0/imm32/next
35580     68/push 0/imm32/outputs
35581     68/push 0/imm32/outputs
35582     56/push-esi/inouts
35583     68/push 0x11/imm32/alloc-id:fake
35584     68/push 0/imm32/operation
35585     68/push 0/imm32/operation
35586     68/push 1/imm32/tag:stmt1
35587     89/<- %esi 4/r32/esp
35588 $test-compare-mem-with-literal:initialize-stmt-operation:
35589     # stmt->operation = "compare"
35590     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
35591     (copy-array Heap "compare" %eax)
35592     # convert
35593     c7 0/subop/copy *Curr-block-depth 0/imm32
35594     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
35595     (flush _test-output-buffered-file)
35596 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
35602     # check output
35603     (check-next-stream-line-equal _test-output-stream "81 7/subop/compare *(ebp+0x00000008) 0x34/imm32" "F - test-compare-mem-with-literal")
35604     # . epilogue
35605     89/<- %esp 5/r32/ebp
35606     5d/pop-to-ebp
35607     c3/return
35608 
35609 test-compare-eax-with-literal:
35610     #   compare var1/eax 0x34
35611     # =>
35612     #   3d/compare-eax-with 0x34/imm32
35613     #
35614     # . prologue
35615     55/push-ebp
35616     89/<- %ebp 4/r32/esp
35617     # setup
35618     (clear-stream _test-output-stream)
35619     (clear-stream $_test-output-buffered-file->buffer)
35620 $test-compare-eax-with-literal:initialize-type:
35621     # var type/ecx: (payload type-tree) = int
35622     68/push 0/imm32/right:null
35623     68/push 0/imm32/right:null
35624     68/push 0/imm32/left:unused
35625     68/push 1/imm32/value:int
35626     68/push 1/imm32/is-atom?:true
35627     68/push 0x11/imm32/alloc-id:fake:payload
35628     89/<- %ecx 4/r32/esp
35629 $test-compare-eax-with-literal:initialize-var1:
35630     # var var1/ecx: (payload var)
35631     68/push 0/imm32/register
35632     68/push 0/imm32/register
35633     68/push 0/imm32/no-stack-offset
35634     68/push 1/imm32/block-depth
35635     51/push-ecx
35636     68/push 0x11/imm32/alloc-id:fake
35637     68/push 0/imm32/name
35638     68/push 0/imm32/name
35639     68/push 0x11/imm32/alloc-id:fake:payload
35640     89/<- %ecx 4/r32/esp
35641 $test-compare-eax-with-literal:initialize-var1-name:
35642     # var1->name = "var1"
35643     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
35644     (copy-array Heap "var1" %eax)
35645 $test-compare-eax-with-literal:initialize-var1-register:
35646     # v->register = "eax"
35647     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
35648     (copy-array Heap "eax" %eax)
35649 $test-compare-eax-with-literal:initialize-literal-type:
35650     # var type/edx: (payload type-tree) = literal
35651     68/push 0/imm32/right:null
35652     68/push 0/imm32/right:null
35653     68/push 0/imm32/left:unused
35654     68/push 0/imm32/value:literal
35655     68/push 1/imm32/is-atom?:true
35656     68/push 0x11/imm32/alloc-id:fake:payload
35657     89/<- %edx 4/r32/esp
35658 $test-compare-eax-with-literal:initialize-literal:
35659     # var l/edx: (payload var)
35660     68/push 0/imm32/register
35661     68/push 0/imm32/register
35662     68/push 0/imm32/no-stack-offset
35663     68/push 1/imm32/block-depth
35664     52/push-edx
35665     68/push 0x11/imm32/alloc-id:fake
35666     68/push 0/imm32/name
35667     68/push 0/imm32/name
35668     68/push 0x11/imm32/alloc-id:fake:payload
35669     89/<- %edx 4/r32/esp
35670 $test-compare-eax-with-literal:initialize-literal-value:
35671     # l->name = "0x34"
35672     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
35673     (copy-array Heap "0x34" %eax)
35674 $test-compare-eax-with-literal:initialize-inouts:
35675     # var inouts/esi: (payload stmt-var) = [l]
35676     68/push 0/imm32/is-deref:false
35677     68/push 0/imm32/next
35678     68/push 0/imm32/next
35679     52/push-edx/l
35680     68/push 0x11/imm32/alloc-id:fake
35681     68/push 0x11/imm32/alloc-id:fake:payload
35682     89/<- %esi 4/r32/esp
35683     # var inouts = (handle stmt-var) = [var1, var2]
35684     68/push 0/imm32/is-deref:false
35685     56/push-esi/next
35686     68/push 0x11/imm32/alloc-id:fake
35687     51/push-ecx/var1
35688     68/push 0x11/imm32/alloc-id:fake
35689     68/push 0x11/imm32/alloc-id:fake:payload
35690     89/<- %esi 4/r32/esp
35691 $test-compare-eax-with-literal:initialize-stmt:
35692     # var stmt/esi: (addr statement)
35693     68/push 0/imm32/next
35694     68/push 0/imm32/next
35695     68/push 0/imm32/outputs
35696     68/push 0/imm32/outputs
35697     56/push-esi/inouts
35698     68/push 0x11/imm32/alloc-id:fake
35699     68/push 0/imm32/operation
35700     68/push 0/imm32/operation
35701     68/push 1/imm32/tag:stmt1
35702     89/<- %esi 4/r32/esp
35703 $test-compare-eax-with-literal:initialize-stmt-operation:
35704     # stmt->operation = "compare"
35705     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
35706     (copy-array Heap "compare" %eax)
35707     # convert
35708     c7 0/subop/copy *Curr-block-depth 0/imm32
35709     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
35710     (flush _test-output-buffered-file)
35711 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
35717     # check output
35718     (check-next-stream-line-equal _test-output-stream "3d/compare-eax-with 0x34/imm32" "F - test-compare-eax-with-literal")
35719     # . epilogue
35720     89/<- %esp 5/r32/ebp
35721     5d/pop-to-ebp
35722     c3/return
35723 
35724 test-compare-reg-with-literal:
35725     #   compare var1/ecx 0x34
35726     # =>
35727     #   81 7/subop/compare %ecx 0x34/imm32
35728     #
35729     # . prologue
35730     55/push-ebp
35731     89/<- %ebp 4/r32/esp
35732     # setup
35733     (clear-stream _test-output-stream)
35734     (clear-stream $_test-output-buffered-file->buffer)
35735 $test-compare-reg-with-literal:initialize-type:
35736     # var type/ecx: (payload type-tree) = int
35737     68/push 0/imm32/right:null
35738     68/push 0/imm32/right:null
35739     68/push 0/imm32/left:unused
35740     68/push 1/imm32/value:int
35741     68/push 1/imm32/is-atom?:true
35742     68/push 0x11/imm32/alloc-id:fake:payload
35743     89/<- %ecx 4/r32/esp
35744 $test-compare-reg-with-literal:initialize-var1:
35745     # var var1/ecx: (payload var)
35746     68/push 0/imm32/register
35747     68/push 0/imm32/register
35748     68/push 0/imm32/no-stack-offset
35749     68/push 1/imm32/block-depth
35750     51/push-ecx
35751     68/push 0x11/imm32/alloc-id:fake
35752     68/push 0/imm32/name
35753     68/push 0/imm32/name
35754     68/push 0x11/imm32/alloc-id:fake:payload
35755     89/<- %ecx 4/r32/esp
35756 $test-compare-reg-with-literal:initialize-var1-name:
35757     # var1->name = "var1"
35758     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
35759     (copy-array Heap "var1" %eax)
35760 $test-compare-reg-with-literal:initialize-var1-register:
35761     # v->register = "ecx"
35762     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
35763     (copy-array Heap "ecx" %eax)
35764 $test-compare-reg-with-literal:initialize-literal-type:
35765     # var type/edx: (payload type-tree) = literal
35766     68/push 0/imm32/right:null
35767     68/push 0/imm32/right:null
35768     68/push 0/imm32/left:unused
35769     68/push 0/imm32/value:literal
35770     68/push 1/imm32/is-atom?:true
35771     68/push 0x11/imm32/alloc-id:fake:payload
35772     89/<- %edx 4/r32/esp
35773 $test-compare-reg-with-literal:initialize-literal:
35774     # var l/edx: (payload var)
35775     68/push 0/imm32/register
35776     68/push 0/imm32/register
35777     68/push 0/imm32/no-stack-offset
35778     68/push 1/imm32/block-depth
35779     52/push-edx
35780     68/push 0x11/imm32/alloc-id:fake
35781     68/push 0/imm32/name
35782     68/push 0/imm32/name
35783     68/push 0x11/imm32/alloc-id:fake:payload
35784     89/<- %edx 4/r32/esp
35785 $test-compare-reg-with-literal:initialize-literal-value:
35786     # l->name = "0x34"
35787     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
35788     (copy-array Heap "0x34" %eax)
35789 $test-compare-reg-with-literal:initialize-inouts:
35790     # var inouts/esi: (payload stmt-var) = [l]
35791     68/push 0/imm32/is-deref:false
35792     68/push 0/imm32/next
35793     68/push 0/imm32/next
35794     52/push-edx/l
35795     68/push 0x11/imm32/alloc-id:fake
35796     68/push 0x11/imm32/alloc-id:fake:payload
35797     89/<- %esi 4/r32/esp
35798     # var inouts = (handle stmt-var) = [var1, var2]
35799     68/push 0/imm32/is-deref:false
35800     56/push-esi/next
35801     68/push 0x11/imm32/alloc-id:fake
35802     51/push-ecx/var1
35803     68/push 0x11/imm32/alloc-id:fake
35804     68/push 0x11/imm32/alloc-id:fake:payload
35805     89/<- %esi 4/r32/esp
35806 $test-compare-reg-with-literal:initialize-stmt:
35807     # var stmt/esi: (addr statement)
35808     68/push 0/imm32/next
35809     68/push 0/imm32/next
35810     68/push 0/imm32/outputs
35811     68/push 0/imm32/outputs
35812     56/push-esi/inouts
35813     68/push 0x11/imm32/alloc-id:fake
35814     68/push 0/imm32/operation
35815     68/push 0/imm32/operation
35816     68/push 1/imm32/tag:stmt1
35817     89/<- %esi 4/r32/esp
35818 $test-compare-reg-with-literal:initialize-stmt-operation:
35819     # stmt->operation = "compare"
35820     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
35821     (copy-array Heap "compare" %eax)
35822     # convert
35823     c7 0/subop/copy *Curr-block-depth 0/imm32
35824     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
35825     (flush _test-output-buffered-file)
35826 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
35832     # check output
35833     (check-next-stream-line-equal _test-output-stream "81 7/subop/compare %ecx 0x34/imm32" "F - test-compare-reg-with-literal")
35834     # . epilogue
35835     89/<- %esp 5/r32/ebp
35836     5d/pop-to-ebp
35837     c3/return
35838 
35839 test-emit-subx-stmt-function-call:
35840     # Call a function on a variable on the stack.
35841     #   f foo
35842     # =>
35843     #   (f *(ebp-8))
35844     # (Changing the function name supports overloading in general, but here it
35845     # just serves to help disambiguate things.)
35846     #
35847     # There's a variable on the var stack as follows:
35848     #   name: 'foo'
35849     #   type: int
35850     #   stack-offset: -8
35851     #
35852     # There's nothing in primitives.
35853     #
35854     # We don't perform any checking here on the type of 'f'.
35855     #
35856     # . prologue
35857     55/push-ebp
35858     89/<- %ebp 4/r32/esp
35859     # setup
35860     (clear-stream _test-output-stream)
35861     (clear-stream $_test-output-buffered-file->buffer)
35862 $test-emit-subx-function-call:initialize-type:
35863     # var type/ecx: (payload type-tree) = int
35864     68/push 0/imm32/right:null
35865     68/push 0/imm32/right:null
35866     68/push 0/imm32/left:unused
35867     68/push 1/imm32/value:int
35868     68/push 1/imm32/is-atom?:true
35869     68/push 0x11/imm32/alloc-id:fake:payload
35870     89/<- %ecx 4/r32/esp
35871 $test-emit-subx-function-call:initialize-var:
35872     # var var-foo/ecx: (payload var) = var(type)
35873     68/push 0/imm32/no-register
35874     68/push 0/imm32/no-register
35875     68/push -8/imm32/stack-offset
35876     68/push 1/imm32/block-depth
35877     51/push-ecx/type
35878     68/push 0x11/imm32/alloc-id:fake
35879     68/push 0/imm32/name
35880     68/push 0/imm32/name
35881     68/push 0x11/imm32/alloc-id:fake:payload
35882     89/<- %ecx 4/r32/esp
35883 $test-emit-subx-function-call:initialize-var-name:
35884     # var-foo->name = "foo"
35885     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
35886     (copy-array Heap "foo" %eax)
35887 $test-emit-subx-function-call:initialize-stmt-var:
35888     # var operand/ebx: (payload stmt-var) = stmt-var(var-foo)
35889     68/push 0/imm32/is-deref:false
35890     68/push 0/imm32/next
35891     68/push 0/imm32/next
35892     51/push-ecx/var-foo
35893     68/push 0x11/imm32/alloc-id:fake
35894     68/push 0x11/imm32/alloc-id:fake:payload
35895     89/<- %ebx 4/r32/esp
35896 $test-emit-subx-function-call:initialize-stmt:
35897     # var stmt/esi: (addr statement)
35898     68/push 0/imm32/no-outputs
35899     68/push 0/imm32/no-outputs
35900     53/push-ebx/inouts
35901     68/push 0x11/imm32/alloc-id:fake
35902     68/push 0/imm32/operation
35903     68/push 0/imm32/operation
35904     68/push 1/imm32/tag
35905     89/<- %esi 4/r32/esp
35906 $test-emit-subx-function-call:initialize-stmt-operation:
35907     # stmt->operation = "f"
35908     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
35909     (copy-array Heap "f" %eax)
35910     # convert
35911     c7 0/subop/copy *Curr-block-depth 0/imm32
35912     (emit-subx-stmt _test-output-buffered-file %esi 0 0 Stderr 0)
35913     (flush _test-output-buffered-file)
35914 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
35920     # check output
35921     (check-next-stream-line-equal _test-output-stream "(f *(ebp+0xfffffff8))" "F - test-emit-subx-stmt-function-call")
35922     # . epilogue
35923     89/<- %esp 5/r32/ebp
35924     5d/pop-to-ebp
35925     c3/return
35926 
35927 test-emit-subx-stmt-function-call-with-literal-arg:
35928     # Call a function on a literal.
35929     #   f 0x34
35930     # =>
35931     #   (f2 0x34)
35932     #
35933     # . prologue
35934     55/push-ebp
35935     89/<- %ebp 4/r32/esp
35936     # setup
35937     (clear-stream _test-output-stream)
35938     (clear-stream $_test-output-buffered-file->buffer)
35939 $test-emit-subx-function-call-with-literal-arg:initialize-type:
35940     # var type/ecx: (payload type-tree) = int
35941     68/push 0/imm32/right:null
35942     68/push 0/imm32/right:null
35943     68/push 0/imm32/left:unused
35944     68/push 0/imm32/value:literal
35945     68/push 1/imm32/is-atom?:true
35946     68/push 0x11/imm32/alloc-id:fake:payload
35947     89/<- %ecx 4/r32/esp
35948 $test-emit-subx-function-call-with-literal-arg:initialize-var:
35949     # var var-foo/ecx: (payload var) = var(lit)
35950     68/push 0/imm32/no-register
35951     68/push 0/imm32/no-register
35952     68/push 0/imm32/no-stack-offset
35953     68/push 1/imm32/block-depth
35954     51/push-ecx/type
35955     68/push 0x11/imm32/alloc-id:fake
35956     68/push 0/imm32/name
35957     68/push 0/imm32/name
35958     68/push 0x11/imm32/alloc-id:fake:payload
35959     89/<- %ecx 4/r32/esp
35960 $test-emit-subx-function-call-with-literal-arg:initialize-var-name:
35961     # var-foo->name = "0x34"
35962     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
35963     (copy-array Heap "0x34" %eax)
35964 $test-emit-subx-function-call-with-literal-arg:initialize-stmt-var:
35965     # var operand/ebx: (payload stmt-var) = stmt-var(var-foo)
35966     68/push 0/imm32/is-deref:false
35967     68/push 0/imm32/next
35968     68/push 0/imm32/next
35969     51/push-ecx/var-foo
35970     68/push 0x11/imm32/alloc-id:fake
35971     68/push 0x11/imm32/alloc-id:fake:payload
35972     89/<- %ebx 4/r32/esp
35973 $test-emit-subx-function-call-with-literal-arg:initialize-stmt:
35974     # var stmt/esi: (addr statement)
35975     68/push 0/imm32/no-outputs
35976     68/push 0/imm32/no-outputs
35977     53/push-ebx/inouts
35978     68/push 0x11/imm32/alloc-id:fake
35979     68/push 0/imm32/operation
35980     68/push 0/imm32/operation
35981     68/push 1/imm32/tag
35982     89/<- %esi 4/r32/esp
35983 $test-emit-subx-function-call-with-literal-arg:initialize-stmt-operation:
35984     # stmt->operation = "f"
35985     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
35986     (copy-array Heap "f" %eax)
35987     # convert
35988     c7 0/subop/copy *Curr-block-depth 0/imm32
35989     (emit-subx-stmt _test-output-buffered-file %esi 0 %ebx 0 Stderr 0)
35990     (flush _test-output-buffered-file)
35991 +--  6 lines: #?     # dump _test-output-stream --------------------------------------------------------------------------------------------------------------------------------------------------------------------
35997     # check output
35998     (check-next-stream-line-equal _test-output-stream "(f 0x34)" "F - test-emit-subx-stmt-function-call-with-literal-arg")
35999     # . epilogue
36000     89/<- %esp 5/r32/ebp
36001     5d/pop-to-ebp
36002     c3/return
36003 
36004 emit-indent:  # out: (addr buffered-file), n: int
36005     # . prologue
36006     55/push-ebp
36007     89/<- %ebp 4/r32/esp
36008     # . save registers
36009     50/push-eax
36010     # var i/eax: int = n
36011     8b/-> *(ebp+0xc) 0/r32/eax
36012     {
36013       # if (i <= 0) break
36014       3d/compare-eax-with 0/imm32
36015       7e/jump-if-<= break/disp8
36016       (write-buffered *(ebp+8) "  ")
36017       48/decrement-eax
36018       eb/jump loop/disp8
36019     }
36020 $emit-indent:end:
36021     # . restore registers
36022     58/pop-to-eax
36023     # . epilogue
36024     89/<- %esp 5/r32/ebp
36025     5d/pop-to-ebp
36026     c3/return
36027 
36028 emit-subx-prologue:  # out: (addr buffered-file)
36029     # . prologue
36030     55/push-ebp
36031     89/<- %ebp 4/r32/esp
36032     #
36033     (write-buffered *(ebp+8) "  # . prologue\n")
36034     (write-buffered *(ebp+8) "  55/push-ebp\n")
36035     (write-buffered *(ebp+8) "  89/<- %ebp 4/r32/esp\n")
36036 $emit-subx-prologue:end:
36037     # . epilogue
36038     89/<- %esp 5/r32/ebp
36039     5d/pop-to-ebp
36040     c3/return
36041 
36042 emit-subx-epilogue:  # out: (addr buffered-file)
36043     # . prologue
36044     55/push-ebp
36045     89/<- %ebp 4/r32/esp
36046     #
36047     (write-buffered *(ebp+8) "  # . epilogue\n")
36048     (write-buffered *(ebp+8) "  89/<- %esp 5/r32/ebp\n")
36049     (write-buffered *(ebp+8) "  5d/pop-to-ebp\n")
36050     (write-buffered *(ebp+8) "  c3/return\n")
36051 $emit-subx-epilogue:end:
36052     # . epilogue
36053     89/<- %esp 5/r32/ebp
36054     5d/pop-to-ebp
36055     c3/return